diff --git a/.babelrc b/.babelrc new file mode 100644 index 000000000..5c9d91c2d --- /dev/null +++ b/.babelrc @@ -0,0 +1,15 @@ +{ + "presets": [ + [ + "next/babel", + { + "preset-env": { + "exclude": ["transform-exponentiation-operator"] + } + } + ] + ], + "plugins": [ + "babel-plugin-styled-components" + ] +} diff --git a/.claude/skills/visual-verify/.gitignore b/.claude/skills/visual-verify/.gitignore new file mode 100644 index 000000000..10675bc7d --- /dev/null +++ b/.claude/skills/visual-verify/.gitignore @@ -0,0 +1,2 @@ +# Auto-installed csm-dev-wallet + generated screenshots (not source) +.cache/ diff --git a/.claude/skills/visual-verify/SKILL.md b/.claude/skills/visual-verify/SKILL.md new file mode 100644 index 000000000..7f17edf59 --- /dev/null +++ b/.claude/skills/visual-verify/SKILL.md @@ -0,0 +1,178 @@ +--- +name: visual-verify +description: >- + Use when you need to SEE, screenshot, preview, or visually QA how a page of the running CSM or CM + widget looks — connected as a specific wallet address or node operator, or in the disconnected/welcome + state — which a plain headless browser can't reach (it has no wallet). Opens the running app (localhost + or a testnet URL), navigates any route, optionally in dark/light theme, a mobile/desktop viewport, or + cropped to one element, and captures a screenshot plus any console/network errors. E.g. "show the + dashboard as operator 4", "settings in dark mode", "the bond page on mobile", "screenshot the welcome + screen", or "open cm.testnet.fi as operator 5". NOT for: writing unit/e2e tests, debugging + connector/wallet code, building UI features, or comparing against Figma. +--- + +# Visual verification of the running app + +This app is a Web3 dApp: every meaningful page requires a connected wallet. A vanilla automated +browser has no `window.ethereum`, so the connect modal has nothing to click and you only ever see +the welcome screen. This skill solves that with **csm-dev-wallet** — a dev wallet extension that +injects a provider and lets you connect as _any_ address or node operator without keys or signing +(the app runs on Hoodi testnet, where watch-only is enough to render every connected page). + +## Prerequisites + +- A target app must be reachable — the local dev server at `http://localhost:3000` (`yarn dev`), the + CM instance (e.g. `localhost:3001`), or a remote testnet (`--url https://csm.testnet.fi`). This skill + does **not** start anything — check first (`curl -sI `), and ask the user to run `yarn dev` if local is down. +- Which **module** (CSM vs CM) and **chain** the target runs on are detected automatically from the app + itself, so the same command works against any instance — no need to know or pass them. +- `csm-dev-wallet` is auto-installed into `.claude/skills/visual-verify/.cache/` on first run (it's a + QA tool, deliberately kept out of the project's `package.json`). `playwright` is reused from the repo. + +## Quickstart — screenshot any page in any state + +```bash +# Dashboard, connected as node operator #4 (resolves the operator's manager address automatically) +node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --route / + +# Settings, as operator #4's rewards address +node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --role rewards --route /settings + +# Any route, connected as a raw address +node .claude/skills/visual-verify/scripts/verify.mjs --address 0xd8dA…96045 --route /keys + +# A different instance — the CM-module app, or a remote testnet. Module + chain auto-detected from the URL. +node .claude/skills/visual-verify/scripts/verify.mjs --url http://localhost:3001 --operator 2 +node .claude/skills/visual-verify/scripts/verify.mjs --url https://cm.testnet.fi --operator 5 + +# Dark mode, and a mobile-width layout (combine freely) +node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --theme dark +node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --viewport mobile --theme dark + +# Just one element (cropped, scrolled into view) instead of the whole page +node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --selector '[data-testid="accountSectionHeader"]' + +# The disconnected/welcome state — no wallet at all (operator/address not required) +node .claude/skills/visual-verify/scripts/verify.mjs --no-connect --route / + +# Watch it happen live, and leave the browser open to poke around +node .claude/skills/visual-verify/scripts/verify.mjs --operator 12 --headed --keep-open +``` + +It prints the resulting `STATE` (url / connected / account / operator), confirms the requested operator +is the one actually shown, a **page-health** line (console errors, uncaught exceptions, failed + 4xx/5xx +requests), and a screenshot path — then **Read the PNG to actually look at it**. The health line is what +catches a page that _looks_ fine but is actually broken (e.g. a dev server serving 404 chunks). If a run +fails at any step, it still saves a `FAILED-*.png` of wherever it got stuck (and reports its path) — a +failure image usually shows the cause (a modal that never opened, a blank card, the wrong route). + +**`--operator N` guarantees operator N is displayed.** Many operators share an address (e.g. one address +is the rewards address of operators 4, 36 and 318). Connecting only pins the _address_; the app then shows +a default operator (the first or last-cached), which may be a sibling, not N. So after connecting the +script switches the in-app operator selection to N and verifies it — if N isn't available for the resolved +address, it errors and lists what _is_ available. (`--address` has no specific operator, so no switch.) + +Default output is `.cache/shots/-.png` (prefixed with module + any theme/viewport variant +so they don't collide); override with `--out path.png` (relative paths resolve to cwd). Flags: +`--url ` (default `$APP_ORIGIN` / `localhost:3000`) | `--operator N` | `--address 0x…` | +`--role manager|rewards|owner` (default `manager`) | `--route /path` | `--theme light|dark` | +`--viewport mobile|tablet|desktop|WxH` | `--selector ` (shoot one element) | +`--no-connect` (capture with no wallet; operator/address not required) | `--json` | +`--module csm|cm` | `--chain 560048` | `--headed` | `--keep-open` | `--full` (full-page) | +`--out file.png`. **`--module` and `--chain` are auto-detected from the target URL** — only pass them to override. + +`--json` emits one structured object on **stdout** (progress logs go to stderr) with the connection +details, `state`, the screenshot path, and `health` + full `diagnostics` (the console/network errors). +Use it when an agent needs to act on the result — `health.total > 0` is the machine-readable "this page +has problems" signal even when the screenshot looks fine. On failure it prints `{ "ok": false, "error" }` +and exits non-zero. + +`--theme` works via `prefers-color-scheme` (the app honours it), set before first paint and verified by +page-background luminance, with the header theme toggler as fallback — so it's reliable even at mobile +widths where the toggler hides in a menu. `--viewport` presets: mobile `390×844`, tablet `768×1024`, +desktop `1280×800` (or pass an explicit `WIDTHxHEIGHT`). + +## Finding operators + +To pick an operator — or find an address that controls several (needed to exercise the in-app +operator switcher, which changes operator _without_ a wallet change): + +```bash +node .claude/skills/visual-verify/scripts/operators.mjs # summary + multi-operator addresses +node .claude/skills/visual-verify/scripts/operators.mjs --id 4 # full details for operator #4 +``` + +## How it connects (the non-obvious bits) + +These quirks are already handled in `scripts/lib.mjs`; understand them before writing custom flows: + +- **Connection is seeded, not clicked (with a modal fallback).** Setting `eth_accounts` alone does NOT + auto-connect — wagmi/reef-knot only adopt a connection from persisted storage or an explicit connector + call. So `connectAs` writes the exact 4 `localStorage` keys a real connect leaves behind (terms-accepted + flag + `wagmi.recentConnectorId`/`reconnect-wallet-id` + the `wagmi.store` connection record) via + `addInitScript` **before load**, and the app reconnects the injected wallet on boot — no clicks. If that + reconnect doesn't take (e.g. wagmi bumps `wagmi.store`'s schema or the `reef-knot_accept-terms_n2` + version suffix drifts), it falls back to the **proven modal flow**: `connectBtn` → tick the Terms + checkbox (it gates the wallet buttons) → click the **"Browser"** option (the injected provider shows up + under the pinned `browserExtension` connector, not by the wallet's own name). +- **The header chip re-renders asynchronously** after any navigation, reload, or account change (wagmi + reconnects, balances fetch). Always wait for the header to settle into connected-or-disconnected + before reading state or screenshotting, or you capture a blank chip. `settle()` does this. +- **Wallet account vs active operator are two layers.** One address can manage many operators; the app's + switcher (`data-testid="nodeOperatorHeader"`) changes the active operator with no wallet event. The + in-app operator selection is connection-scoped — it resets to the default operator on reconnect/reload, + which is why `connectAs` re-asserts it (via `ensureOperator`) _after_ the final navigation, not before. + +## Writing custom multi-step flows + +For scenarios beyond a single screenshot (persistence checks, account switching, the operator switcher, +disconnect/reconnect), import the library instead of shelling out to the CLI: + +```js +import { connectAs, ensureOperator, readState, settle, HOODI } from './lib.mjs'; + +const { context, wallet, page } = await connectAs({ + operatorId: 318, + route: '/settings', +}); +await wallet.switchAccount(page, '0xba99…26af'); // change wallet account → app reacts live +await settle(page); +await ensureOperator(page, 36); // switch in-app operator (no wallet change) +console.log(await readState(page)); // { url, connected, account, operator } +await page.screenshot({ path: 'after-switch.png' }); +await context.close(); +``` + +`connectAs(...)` returns Playwright's `context`/`page` plus the dev-wallet `wallet` controller, and (for +`operatorId`) guarantees that operator is active. Helpers: `ensureOperator(page, id)` (in-app switch + +verify), `currentOperatorId(page)`, `readState`, `settle`, `connectModal`. Key `wallet` methods: +`switchAccount(page, addr)`, `switchNetwork(page, chainId)`, `disconnect(page)`, +`selectOperator(page, id, role)`, `refreshOperators(page, chainId, module)`, `getOperator(page, id, …)`. +Full controller API, the underlying `wallet_test*` RPC primitives (for drivers that can't use the +helper), and a **dev-browser fallback** (for headed/persistent sessions) are in +[references/advanced.md](references/advanced.md). + +## Key app facts + +- Network: Hoodi testnet, `chainId 560048` (auto-detected per instance). The app's RPC proxy + (`/api/rpc`) is reused to resolve operators. +- **CSM vs CM**: the app serves one module per instance (`MODULE` env). They have _different_ operator + sets, so an id valid in CSM may not exist in CM. `operators.mjs --url ` lists the right set. + The connect flow, header testids, and switcher are shared across both modules. +- Header testids: `accountSectionHeader` (wallet chip), `nodeOperatorHeader` (active operator + switcher), + `connectBtn` (shown only when disconnected). Account modal: `disconnectBtn`, `connectedAddress`. + Operator switcher rows: `switchModalOperatorRow`, with a "Switch" button per non-current row. +- Routes are normal Next.js paths: `/`, `/keys`, `/settings` (redirects to a sub-tab like + `/settings/roles`), etc. Use whatever the app's nav exposes. +- `MODULE` (csm/cm) is set by the server env; pass `--module` to match if you've switched it. + +## Troubleshooting + +- **Welcome screen / never connects** → app likely on a different `MODULE` or chain than you passed, + or the connect modal changed. Re-run with `--headed` to watch, and check the testids above still exist. +- **`ECONNREFUSED` / blank page** → dev server isn't running; start `yarn dev`. +- **Slow first load** → the dev server cold-compiles on first hit; navigation auto-retries (commit + + app-shell wait, 3 attempts). If it still reports "never became ready", the server is stuck — restart `yarn dev`. +- **Operator resolve fails** → `/api/rpc` proxy unreachable or the id doesn't exist on this chain; try + `operators.mjs` to list valid ids. +- **Chromium missing** → run `yarn playwright install chromium` (the repo's documented setup step). diff --git a/.claude/skills/visual-verify/references/advanced.md b/.claude/skills/visual-verify/references/advanced.md new file mode 100644 index 000000000..38791dc5e --- /dev/null +++ b/.claude/skills/visual-verify/references/advanced.md @@ -0,0 +1,98 @@ +# Advanced: full wallet API, RPC primitives, and the dev-browser fallback + +Read this when a single screenshot via `verify.mjs` isn't enough — e.g. you're scripting a stateful +scenario, driving the browser through a tool other than the bundled Playwright helper, or you need a +headed/persistent session. + +## csm-dev-wallet — Playwright helper API + +`import { launch } from 'csm-dev-wallet/playwright'` → +`const { context, wallet, extensionId } = await launch({ headless: true })`. + +`wallet` (the `WalletController`): + +| Method | Purpose | +| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `setup({ origin, network, account?, signingMode?, … })` | Pre-configure state via the service worker **before** navigating. Sets which account `eth_accounts` returns. Note: does NOT auto-connect the dApp — you still drive the connect modal. | +| `switchAccount(page, address, source?)` | Set active account; emits `accountsChanged` (app reacts live). | +| `switchNetwork(page, chainId)` | Set active chain; emits `chainChanged`. | +| `connect(page, address?, source?)` | Wallet-side connect. | +| `disconnect(page)` | Emits `accountsChanged([])`. | +| `selectOperator(page, operatorId, role, chainId?, module?)` | Resolve an operator's role address from cache, set it active. | +| `refreshOperators(page, chainId?, module?, rpcUrl?)` | Fetch live operators from RPC, cache, return them. | +| `getOperators(page, chainId?, module?)` / `getOperator(page, id, …)` | Read cached operators. | +| `seedOperators(page, ops, chainId, module?)` | Inject operators into cache. | +| `setRpcUrl(page, chainId, url)` | Point the wallet at an RPC (we use the app's `/api/rpc`). | +| `setSigningMode(page, 'approve'\|'reject'\|'error'\|'prompt')` | How signing requests behave (only matters for tx flows; visual checks don't need it). | + +`SetupOptions` of note: `account` (auto-return this address), `network` (defaults 1 — pass 560048 for Hoodi), +`moduleAvailability: { csm, cm }`, `operators` (seed), `signingMode`. On Hoodi/Mainnet the wallet is +watch-only (can't sign); on an Anvil fork it can impersonate for real transactions. + +## Driver-agnostic "set account" RPC primitives + +Any driver that can run JS on the page (Playwright MCP, chrome-devtools, dev-browser, agent-browser) +can control the wallet directly through these custom methods on `window.ethereum`, once the extension +is loaded — no helper required: + +```js +await window.ethereum.request({ + method: 'wallet_testSetNetwork', + params: [{ chainId: 560048 }], +}); +await window.ethereum.request({ + method: 'wallet_testSetAccount', + params: [{ address: '0x…', source: { type: 'manual' } }], +}); +// also: wallet_testConnect, wallet_testDisconnect, wallet_testGetState, wallet_testSetSigningMode, +// wallet_testRefreshOperators, wallet_testGetOperators, wallet_testSetOperatorAccount, wallet_testSetRpcUrl +``` + +`wallet_testSetAccount` emits `accountsChanged`, so the app updates live. Check the provider is present +with `window.ethereum?.isCSMDevWallet === true`. + +## Connect flow (any driver) + +1. Navigate to `http://localhost:3000`. +2. (optional) set account via the RPC above. +3. Click `[data-testid="connectBtn"]`. +4. Tick the Terms/Privacy checkbox (`role=checkbox`; use a forced click — a styled SVG overlays it). +5. Click the wallet option labelled **"Browser"** (NOT MetaMask/OKX/Ledger/Coinbase/WalletConnect). +6. Wait for `[data-testid="accountSectionHeader"]`. Disconnect = click that chip → `[data-testid="disconnectBtn"]`. + +## Driver verdicts (tested) + +- **Playwright helper (bundled here)** — best: headless, no display/GL flags. Use by default. +- **dev-browser** — works, but only via CDP attach to an externally launched, extension-loaded, + **headed + software-GL** Chrome kept alive as a background task (see below). +- **agent-browser** — can load the extension + inject the provider, but headless screenshots deadlock + while an extension is loaded; would need the same headed + swiftshader setup as dev-browser. +- **chrome-devtools-mcp** — cannot: its managed Chrome runs `--disable-extensions` and can't be + reconfigured mid-session or attached to an external CDP browser, so there's no `window.ethereum`. + +## dev-browser fallback (headed / persistent session) + +When you want a persistent, watch-it-live session instead of the headless helper: + +1. Launch external Chrome as a **background task** (plain `&`/`nohup` get reaped on macOS), headed, with + software GL (the dev page's continuous animation starves the default compositor → screenshots hang): + ```bash + "" --use-angle=swiftshader --use-gl=angle --window-size=1366,900 \ + --remote-debugging-port=9323 --user-data-dir=/tmp/devbrowser-prof --no-first-run \ + --disable-extensions-except="" --load-extension="" http://localhost:3000 + ``` + where `` = `.claude/skills/visual-verify/.cache/dist/extension` + and `` is Playwright's chromium (find via + `node -e "console.log(require('playwright').chromium.executablePath())"`). +2. Drive it: `dev-browser --connect http://localhost:9323` (QuickJS; `browser.getPage(...)` → a Playwright + `Page`). Set the account via the `wallet_test*` RPC, then run the connect flow above with forced clicks. + Use `--timeout 60`+ for multi-action scripts; `saveScreenshot` writes to `~/.dev-browser/tmp/` (copy out). + +## Example: a full stateful scenario + +A 10-step scenario (connect → reload-persists → switch operator → settings → reload → change wallet → +in-app operator switch → disconnect/reconnect) was validated on both the Playwright helper and dev-browser +with identical results. Build such flows with `connectAs()` + `wallet.switchAccount()` + +`page.getByTestId('nodeOperatorHeader').click()` then the row's "Switch" button. Key learned behaviours: +connection and route both persist across reload; account changes update the page in-place (no redirect); +the in-app operator switch needs no wallet event; reconnect resets the active operator to the default. diff --git a/.claude/skills/visual-verify/scripts/lib.mjs b/.claude/skills/visual-verify/scripts/lib.mjs new file mode 100644 index 000000000..3bc765007 --- /dev/null +++ b/.claude/skills/visual-verify/scripts/lib.mjs @@ -0,0 +1,473 @@ +// Shared library for visual-verify: launches a browser with the csm-dev-wallet +// extension, connects as a given address/operator on the running app, and exposes +// the wallet controller for richer flows. Keep this dependency-light and the connect +// flow in ONE place so every script (and future agent) inherits the same verified path. +import { execFileSync } from 'node:child_process'; +import { existsSync, mkdirSync, readdirSync, rmSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const SKILL_DIR = join(HERE, '..'); +const CACHE_DIR = join(SKILL_DIR, '.cache'); +const DEV_WALLET_VERSION = '^2.3.0'; +const DIST_DIR = join(CACHE_DIR, 'dist'); +const DIST_ENTRY = join(DIST_DIR, 'playwright/index.js'); +const FULL_INSTALL_ENTRY = join(CACHE_DIR, 'node_modules/csm-dev-wallet/dist/playwright/index.js'); + +export const ORIGIN = process.env.APP_ORIGIN || 'http://localhost:3000'; +export const HOODI = 560048; + +let LOG_STDERR = false; +// Route progress logs to stderr instead of stdout. --json callers enable this so stdout carries ONLY +// the JSON payload (data on stdout, diagnostics on stderr — the conventional split). +export const setQuietLogs = (v = true) => { + LOG_STDERR = v; +}; +export const log = (...a) => + LOG_STDERR + ? process.stderr.write(`[visual-verify] ${a.map((x) => (typeof x === 'string' ? x : JSON.stringify(x))).join(' ')}\n`) + : console.info('[visual-verify]', ...a); + +// Named viewport presets (logical px). Callers pass a preset name or an explicit "WIDTHxHEIGHT". +export const VIEWPORTS = { + mobile: { width: 390, height: 844 }, + tablet: { width: 768, height: 1024 }, + desktop: { width: 1280, height: 800 }, +}; +export const resolveViewport = (spec) => { + if (!spec) return null; + if (VIEWPORTS[spec]) return { name: spec, ...VIEWPORTS[spec] }; + const m = String(spec).match(/^(\d+)x(\d+)$/i); + if (m) return { name: spec, width: Number(m[1]), height: Number(m[2]) }; + throw new Error(`Unknown viewport "${spec}" — use mobile|tablet|desktop or WIDTHxHEIGHT (e.g. 414x896)`); +}; + +// csm-dev-wallet isn't a project dependency (it's a dev/QA tool). Resolve it from the +// project if present; otherwise acquire it into an isolated cache so we never mutate the +// repo's package.json/node_modules. We only need the prebuilt `dist/` (~712KB: the +// extension + the Playwright helper), NOT the package's heavy build deps (react/viem/two +// Lido SDKs, ~149MB). At runtime `dist/playwright/index.js` imports only path/url + a bare +// `import 'playwright'` — which Node resolves UP the tree to the repo's existing install — +// so fetching just the tarball and extracting `dist/` is enough, and ~30s faster. +export const loadDevWallet = async () => { + // 1. Project devDep, if ever added. Cheapest path; let Node's resolver handle it. + try { + return await import('csm-dev-wallet/playwright'); + } catch { + /* fall through to cache */ + } + // 2. Already-extracted dist in the cache → instant on repeat runs. + if (existsSync(DIST_ENTRY)) { + return import(pathToFileURL(DIST_ENTRY).href); + } + // 3. Lean first run: pack the tarball, extract only `package/dist`. + try { + return await fetchDistOnly(); + } catch (e) { + // 4. Self-heal: if the lean import fails because a *future* helper version grew a new + // runtime dependency (bare import that isn't in the repo's tree), fall back to a full + // `npm install` so its node_modules are present. Only triggers on real dependency + // drift — the common case stays lean. + if (e?.code !== 'ERR_MODULE_NOT_FOUND') throw e; + log(`lean dist is missing a runtime dependency (${e.message.split('\n')[0]}) — falling back to full install`); + return fullInstall(); + } +}; + +// Fetch just the published tarball and extract its `dist/` into CACHE_DIR/dist, then import +// the helper. `npm pack` downloads the .tgz without touching node_modules; `tar --strip-components=1 +// package/dist` lands `package/dist/playwright` → CACHE_DIR/dist/playwright and likewise for +// the extension, so the helper's `resolve(__dirname, "../extension")` points at CACHE_DIR/dist/extension. +const fetchDistOnly = async () => { + log(`csm-dev-wallet not found — fetching ${DEV_WALLET_VERSION} dist into ${CACHE_DIR} (one-time, lean)…`); + mkdirSync(CACHE_DIR, { recursive: true }); + // execFileSync (no shell): args as an array so versions/paths can't be read as shell metacharacters. + // --silent so the only stdout is the produced filename; trim CR/whitespace npm may append. + const tgzName = execFileSync( + 'npm', + ['pack', `csm-dev-wallet@${DEV_WALLET_VERSION}`, '--pack-destination', CACHE_DIR, '--silent'], + { encoding: 'utf8' }, + ) + .trim() + .split('\n') + .pop() + .trim(); + // Prefer npm's reported name; fall back to globbing the .tgz in CACHE_DIR if stdout was empty. + const tgz = tgzName && existsSync(join(CACHE_DIR, tgzName)) + ? join(CACHE_DIR, tgzName) + : join(CACHE_DIR, readdirSync(CACHE_DIR).find((f) => f.endsWith('.tgz')) ?? ''); + if (!existsSync(tgz)) throw new Error(`npm pack produced no .tgz in ${CACHE_DIR}`); + try { + execFileSync('tar', ['-xzf', tgz, '-C', CACHE_DIR, '--strip-components=1', 'package/dist'], { stdio: 'inherit' }); + } finally { + rmSync(tgz, { force: true }); // the tarball is throwaway once dist/ is extracted + } + if (!existsSync(DIST_ENTRY)) throw new Error(`extracted dist missing ${DIST_ENTRY}`); + return import(pathToFileURL(DIST_ENTRY).href); +}; + +// Full dependency install — the original behaviour, kept as a self-healing fallback for the +// rare case the helper gains a runtime dep the repo doesn't already provide. +const fullInstall = () => { + log(`installing ${DEV_WALLET_VERSION} (full deps) into ${CACHE_DIR}…`); + mkdirSync(CACHE_DIR, { recursive: true }); + execFileSync( + 'npm', + ['install', `csm-dev-wallet@${DEV_WALLET_VERSION}`, '--prefix', CACHE_DIR, '--no-audit', '--no-fund', '--silent'], + { stdio: 'inherit' }, + ); + return import(pathToFileURL(FULL_INSTALL_ENTRY).href); +}; + +const moduleKeys = (role) => + role === 'rewards' ? 'rewardsAddress' : role === 'owner' ? 'ownerAddress' : 'managerAddress'; + +// Detect which module (csm/cm) and chain the target app is serving, straight from its SSR HTML +// (__NEXT_DATA__ carries publicRuntimeConfig.module + defaultChain). This lets a single command +// target any instance — localhost:3000 (CSM), localhost:3001 (CM), csm.testnet.fi, cm.testnet.fi — +// without the caller having to know/match the module or chain, which would otherwise show the wrong +// operators or an "unsupported chain". Explicit overrides win; this only fills the gaps. +export const detectAppConfig = async (origin) => { + try { + const html = await (await fetch(origin)).text(); + const module = (html.match(/"module":"(CSM|CM)"/i)?.[1] || 'CSM').toLowerCase(); + const chainId = Number(html.match(/"defaultChain":(\d+)/)?.[1]) || HOODI; + return { module, chainId }; + } catch (e) { + log(`could not detect app config from ${origin} (${e.message}); assuming csm/${HOODI}`); + return { module: 'csm', chainId: HOODI }; + } +}; + +// Navigate with retries + an app-readiness wait. The local dev server cold-compiles on first hit and +// can hang past `domcontentloaded` (the event never fires) or briefly serve 404 chunks — a single +// plain goto then just times out. Instead: `commit` the navigation (resolves as soon as the response +// starts, not blocked on a slow/stuck load), then wait for the app shell to actually render (the +// connect button or the account chip). On failure, retry the whole navigation — a fresh goto picks up +// freshly-compiled chunks once the server settles. Used for the first load and every route change. +const APP_READY = '[data-testid="connectBtn"], [data-testid="accountSectionHeader"]'; +export const gotoReady = async (page, url, { attempts = 3, navTimeout = 25000, readyTimeout = 25000 } = {}) => { + let lastErr; + for (let i = 1; i <= attempts; i++) { + try { + await page.goto(url, { waitUntil: 'commit', timeout: navTimeout }); + await page.waitForSelector(APP_READY, { state: 'visible', timeout: readyTimeout }); + if (i > 1) log(`navigate ${url}: ready on attempt ${i}`); + return; + } catch (e) { + lastErr = e; + log(`navigate ${url}: attempt ${i}/${attempts} not ready (${e.message.split('\n')[0]})${i < attempts ? ' — retrying' : ''}`); + if (i < attempts) await page.waitForTimeout(1500 * i); + } + } + throw new Error( + `App at ${url} never became ready after ${attempts} attempts — the dev server may still be compiling or serving stale 404 chunks. Re-run, or restart "yarn dev". (last: ${lastErr?.message?.split('\n')[0]})`, + ); +}; + +// Capture page-health signals for the whole session: console errors, uncaught exceptions, failed +// requests, and 4xx/5xx responses. This catches "looks fine but is broken" pages — e.g. a dev server +// serving 404 chunks (invisible in a screenshot) or a runtime error that blanked a card. Extension/ +// data/blob URLs and benign aborted requests (canceled by our navigations) are filtered so the signal +// stays app-relevant. Returns a live object the caller reads after the page settles. +export const attachDiagnostics = (page) => { + const d = { consoleErrors: [], pageErrors: [], failedRequests: [], httpErrors: [] }; + const internal = (url = '') => /^(chrome-extension|data|blob|about):/.test(url); + page.on('console', (m) => { + if (m.type() !== 'error') return; + const text = m.text().slice(0, 400); + if (!d.consoleErrors.some((e) => e.text === text)) d.consoleErrors.push({ text, location: m.location()?.url || undefined }); + }); + page.on('pageerror', (e) => { + const text = String(e?.message || e).slice(0, 400); + if (!d.pageErrors.includes(text)) d.pageErrors.push(text); + }); + page.on('requestfailed', (r) => { + const url = r.url(); + const error = r.failure()?.errorText || ''; + if (internal(url) || error === 'net::ERR_ABORTED') return; // ERR_ABORTED ≈ request canceled by a navigation/reload, not a real fault + if (!d.failedRequests.some((x) => x.url === url)) d.failedRequests.push({ url, method: r.method(), error }); + }); + page.on('response', (r) => { + const status = r.status(); + const url = r.url(); + if (status < 400 || internal(url)) return; + if (!d.httpErrors.some((x) => x.url === url && x.status === status)) d.httpErrors.push({ url, status, method: r.request().method() }); + }); + return d; +}; + +// Roll diagnostics up into per-category counts + a total — for a one-line summary or a JSON field. +export const diagnosticsSummary = (d) => { + const counts = { + consoleErrors: d.consoleErrors.length, + pageErrors: d.pageErrors.length, + failedRequests: d.failedRequests.length, + httpErrors: d.httpErrors.length, + }; + return { total: Object.values(counts).reduce((a, b) => a + b, 0), counts }; +}; + +// Open the app already connected as `address` (or as operator #`operatorId`'s `role` address). +// `origin` may be any instance (defaults to localhost:3000 / $APP_ORIGIN). module/chainId auto-detect +// from the app unless given. Returns { context, wallet, page, diagnostics, address, operator, origin, +// module, chainId, theme, viewport }. Caller is responsible for context.close(). +export const connectAs = async ({ + address, + operatorId, + role = 'manager', + origin = ORIGIN, + module, + chainId, + route = '/', + headless = true, + theme, + viewport, + connect = true, + onPage, // invoked (page, context, diagnostics) as soon as the page exists — lets callers + // screenshot the failure point even if a later step throws. +} = {}) => { + const detected = await detectAppConfig(origin); + module = (module ?? detected.module).toLowerCase(); + chainId = chainId ?? detected.chainId; + log(`target ${origin} — module=${module} chain=${chainId}`); + if (theme && !['light', 'dark'].includes(theme)) throw new Error('--theme must be light or dark'); + const vp = resolveViewport(viewport); + + const { launch } = await loadDevWallet(); + const { context, wallet } = await launch({ headless }); + await wallet.setup({ origin, network: chainId }); + + const page = await context.newPage(); + const diagnostics = attachDiagnostics(page); // start collecting console/network health before any nav + onPage?.(page, context, diagnostics); // hand refs to the caller now, so a failure mid-flow is still screenshot-able + // Set viewport + color scheme BEFORE navigating so the page renders at the right size/theme from + // the first paint. The app follows prefers-color-scheme, so emulateMedia drives the theme without + // touching the toggler (which can be hidden behind a menu at narrow viewports). + if (vp) { + await page.setViewportSize({ width: vp.width, height: vp.height }); + log(`viewport ${vp.name} (${vp.width}x${vp.height})`); + } + if (theme) await page.emulateMedia({ colorScheme: theme }); + + // `connect: false` captures the genuine disconnected/welcome state — no account, no modal, no operator. + // Otherwise we connect by SEEDING the exact localStorage wagmi/reef-knot persist after a real connect, + // so the app auto-reconnects the injected wallet on load — skipping the connectBtn/terms/"Browser" + // clicks. When the address is known upfront (--address) we seed before the first load (one load, no + // modal); for --operator the address needs a page+RPC to resolve, so that case seeds and reloads below. + // `connectModal` stays as a self-healing fallback if a seeded reconnect doesn't take (wagmi.store + // schema bump, terms-version key drift, etc.). + let target = connect ? address || null : null; + if (target) { + await wallet.setup({ origin, network: chainId, account: target }); // eth_accounts returns it from boot + await seedConnection(context, { address: target, chainId }); + } + await gotoReady(page, origin); + + if (connect) { + try { + await wallet.setRpcUrl(page, chainId, `${origin}/api/rpc`); + } catch (e) { + log('setRpcUrl warn:', e.message); + } + + if (!target && operatorId != null) { + // Operator addresses depend on module (CSM/CM differ). refreshOperators pulls live data via the + // app's RPC proxy; on a just-started/recompiling dev server it can come back empty, making + // getOperator throw "not found" — retry once with an explicit rpcUrl, then a clear error. + let op = null; + for (let attempt = 0; attempt < 2 && !op; attempt++) { + await wallet.refreshOperators(page, chainId, module, attempt ? `${origin}/api/rpc` : undefined).catch(() => {}); + op = await wallet.getOperator(page, String(operatorId), chainId, module).catch(() => null); + } + if (!op) { + throw new Error(`Could not load ${module} operator #${operatorId} from ${origin} — is the app fully started and is #${operatorId} a valid ${module} operator? (try scripts/operators.mjs to list valid ids)`); + } + target = op[moduleKeys(role)]; + if (!target) throw new Error(`Operator #${operatorId} has no ${role} address`); + log(`${module} operator #${operatorId} ${role} = ${target}`); + await wallet.switchAccount(page, target); + await seedConnection(context, { address: target, chainId }); + await gotoReady(page, origin); // reload so wagmi boots with the seeded connection + } + if (!target) throw new Error('Provide { address } or { operatorId } (or connect:false to capture the disconnected state)'); + + // Confirm the seeded reconnect actually connected; otherwise fall back to the proven modal flow. + if (await isConnected(page)) { + log('connected via seeded session (modal skipped)'); + } else { + log('seeded reconnect did not take — using the connect modal'); + await wallet.switchAccount(page, target); + await connectModal(page); + } + } + + if (route && route !== '/') { + await gotoReady(page, origin + route); + } + await settle(page); + + // Connecting "as operator N" only pins the wallet ADDRESS. If that address manages several + // operators, the app shows a default (the first / last-cached one), which may not be N — so + // switch the in-app operator selection to N and confirm. Done last, on the final route page, + // because the selection is connection-scoped and a fresh navigation resets it to the default. + let operator = null; + if (connect) { + operator = await currentOperatorId(page); + if (operatorId != null && operator !== String(operatorId)) { + operator = (await ensureOperator(page, operatorId)).operator; + } + } + // Verify the theme took (and fall back to the toggler if emulateMedia were ever ignored). + if (theme) await ensureTheme(page, theme); + return { context, wallet, page, diagnostics, address: target, operator, origin, module, chainId, theme, viewport: vp?.name }; +}; + +// The verified connect flow: connectBtn -> accept Terms checkbox -> pick the injected +// "Browser" wallet -> wait for the header account chip. The Terms checkbox gates the +// wallet buttons, and the injected provider shows up as "Browser" (the browserExtension +// connector), not by the wallet's own name. +export const connectModal = async (page) => { + await page.getByTestId('connectBtn').first().click(); + await page.waitForTimeout(700); + const cb = page.getByRole('checkbox').first(); + if (await cb.isVisible({ timeout: 1500 }).catch(() => false)) { + if (!(await cb.isChecked().catch(() => false))) { + await cb.check({ force: true }).catch(() => cb.click({ force: true })); + } + } + await page.waitForTimeout(300); + await page.locator('button, [role="button"], a').filter({ hasText: /^Browser/ }).first().click(); + await page.getByTestId('accountSectionHeader').first().waitFor({ state: 'visible', timeout: 20000 }); +}; + +// Is a wallet currently connected? (header account chip present). Used to confirm a seeded reconnect. +export const isConnected = (page, timeout = 8000) => + page.getByTestId('accountSectionHeader').first().isVisible({ timeout }).catch(() => false); + +// Seed the EXACT localStorage that wagmi + reef-knot persist after a real connect (captured from a live +// session), so the app auto-reconnects the injected "browserExtension" connector on the next load — +// no connectBtn/terms/"Browser" clicks. Registered via addInitScript, so it lands before the app's JS +// on every navigation in this context. Format notes: reef-knot terms flag is a raw `true`; the wagmi +// connector ids are JSON strings; `wagmi.store` encodes its `connections` Map as {__type:'Map', value} +// keyed by a connection uid that must match `current` and the connector's `uid`. If wagmi/reef-knot bump +// these shapes, the seeded reconnect simply won't take and connectAs falls back to the modal. +export const seedConnection = async (context, { address, chainId }) => { + const uid = 'vv-seeded-connection'; + const store = { + state: { + connections: { + __type: 'Map', + value: [[uid, { accounts: [address], chainId, connector: { id: 'browserExtension', name: 'Browser', type: 'injected', uid } }]], + }, + chainId, + current: uid, + }, + version: 3, + }; + await context.addInitScript( + ([storeJson]) => { + try { + localStorage.setItem('reef-knot_accept-terms_n2', 'true'); + localStorage.setItem('wagmi.recentConnectorId', '"browserExtension"'); + localStorage.setItem('wagmi.reef-knot_reconnect-wallet-id', '"browserExtension"'); + localStorage.setItem('wagmi.store', storeJson); + } catch { + /* localStorage unavailable on this page — harmless; modal fallback covers it */ + } + }, + [JSON.stringify(store)], + ); +}; + +// After any navigation/reload/account-change the header chip re-renders asynchronously +// (wagmi reconnects, balances fetch). Wait for the header to resolve to connected OR +// disconnected before reading/screenshotting, otherwise you capture a blank chip. +export const settle = async (page, extraMs = 2500) => { + await page + .waitForFunction( + () => + document.querySelector('[data-testid="accountSectionHeader"]') || + document.querySelector('[data-testid="connectBtn"]'), + { timeout: 25000 }, + ) + .catch(() => {}); + await page.waitForTimeout(extraMs); +}; + +// Snapshot of what the app currently shows — handy for assertions/logging. +export const readState = (page) => + page.evaluate(() => { + const t = (id) => document.querySelector(`[data-testid="${id}"]`)?.innerText?.replace(/\s+/g, ' ').trim() || null; + return { + url: location.pathname, + connected: !document.querySelector('[data-testid="connectBtn"]'), + account: t('accountSectionHeader'), + operator: t('nodeOperatorHeader'), + }; + }); + +// The numeric id of the operator the app currently shows (from the header chip), or null. +export const currentOperatorId = (page) => + page.evaluate(() => { + const m = (document.querySelector('[data-testid="nodeOperatorHeader"]')?.innerText || '').match(/#(\d+)/); + return m ? m[1] : null; + }); + +// Make the app's ACTIVE operator be #operatorId by driving the in-app switcher. No-op if it's +// already active. This changes only the app-level operator selection, not the wallet account — +// the connected address must manage that operator (else the switcher won't list it and we throw). +export const ensureOperator = async (page, operatorId) => { + const want = String(operatorId); + if ((await currentOperatorId(page)) === want) return { switched: false, operator: want }; + + const header = page.getByTestId('nodeOperatorHeader').first(); + if (!(await header.isVisible({ timeout: 5000 }).catch(() => false))) { + throw new Error(`Cannot select operator #${want}: no operator switcher (is an operator connected?)`); + } + await header.click(); + const rows = page.getByTestId('switchModalOperatorRow'); + await rows.first().waitFor({ state: 'visible', timeout: 10000 }).catch(() => {}); + // `#318(?!\d)` so #31 / #3 don't match #318, and #318 doesn't match #3180. + const target = rows.filter({ hasText: new RegExp(`#${want}(?!\\d)`) }); + if ((await target.count()) === 0) { + const available = (await rows.allInnerTexts().catch(() => [])).map((t) => t.replace(/\s+/g, ' ').trim()); + await page.keyboard.press('Escape').catch(() => {}); + throw new Error(`Operator #${want} not available for the connected address. Switcher shows: ${JSON.stringify(available)}`); + } + await target.first().getByRole('button', { name: 'Switch' }).click(); + await page.waitForTimeout(1500); + await page.keyboard.press('Escape').catch(() => {}); // close modal if it didn't auto-close + await settle(page); + const operator = await currentOperatorId(page); + if (operator !== want) log(`WARN: requested #${want} but header shows #${operator} after switch`); + else log(`switched in-app to operator #${want}`); + return { switched: true, operator }; +}; + +// Detect the app's current theme from the perceived luminance of the page background (light ≈ 0.96, +// dark ≈ 0.11) — independent of any lido-ui/styled-components internals or DOM markers. +export const detectTheme = (page) => + page.evaluate(() => { + const m = getComputedStyle(document.body).backgroundColor.match(/\d+/g); + if (!m) return null; + const [r, g, b] = m.map(Number); + return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 < 0.5 ? 'dark' : 'light'; + }); + +// Force the app into `desired` theme ('light'|'dark'). The app follows prefers-color-scheme, which +// connectAs sets via emulateMedia before load; this verifies it took and, as a fallback, clicks the +// header theme toggler (handles the unlikely case emulateMedia is ignored). Max two clicks. +export const ensureTheme = async (page, desired) => { + for (let i = 0; i < 2; i++) { + if ((await detectTheme(page)) === desired) return desired; + const tog = page.getByTestId('themeToggler').first(); + if (!(await tog.isVisible({ timeout: 2000 }).catch(() => false))) break; + await tog.click({ force: true }); + await page.waitForTimeout(800); + } + const got = await detectTheme(page); + if (got !== desired) log(`WARN: requested ${desired} theme but page looks ${got}`); + return got; +}; diff --git a/.claude/skills/visual-verify/scripts/operators.mjs b/.claude/skills/visual-verify/scripts/operators.mjs new file mode 100644 index 000000000..cc1d1fa72 --- /dev/null +++ b/.claude/skills/visual-verify/scripts/operators.mjs @@ -0,0 +1,61 @@ +#!/usr/bin/env node +// List live operators on the running app's chain via the dev wallet, and surface +// addresses that control multiple operators (useful for testing the in-app operator +// switcher, which lets one address switch operators without a wallet change). +// +// Examples: +// node scripts/operators.mjs # local app: summary + multi-operator addresses +// node scripts/operators.mjs --url http://localhost:3001 # the CM instance (different operator set) +// node scripts/operators.mjs --id 4 # details for operator #4 +// node scripts/operators.mjs --multi # only addresses controlling >1 operator +// module (csm/cm) and chain are auto-detected from --url unless overridden. +import { loadDevWallet, detectAppConfig, ORIGIN, log } from './lib.mjs'; + +const argv = process.argv.slice(2); +const flag = (n, d) => { const i = argv.indexOf(`--${n}`); return i === -1 ? d : argv[i + 1]; }; + +const main = async () => { + const origin = flag('url') || flag('origin') || ORIGIN; + const detected = await detectAppConfig(origin); + const chainId = flag('chain') ? Number(flag('chain')) : detected.chainId; + const module = flag('module') || detected.module; + log(`target ${origin} — module=${module} chain=${chainId}`); + const { launch } = await loadDevWallet(); + const { context, wallet } = await launch({ headless: true }); + await wallet.setup({ origin, network: chainId }); + const page = await context.newPage(); + await page.goto(origin, { waitUntil: 'domcontentloaded', timeout: 60000 }); + await wallet.setRpcUrl(page, chainId, `${origin}/api/rpc`).catch(() => {}); + + const id = flag('id'); + if (id != null) { + await wallet.refreshOperators(page, chainId, module).catch(() => {}); + const op = await wallet.getOperator(page, String(id), chainId, module); + log(`operator #${id}:`, JSON.stringify(op, null, 2)); + await context.close(); + return; + } + + const ops = await wallet.refreshOperators(page, chainId, module); + log(`total operators on chain ${chainId} (${module}): ${ops.length}`); + const byAddr = {}; + for (const o of ops) { + for (const a of [o.managerAddress, o.rewardsAddress]) { + if (!a) continue; + (byAddr[a.toLowerCase()] ||= new Set()).add(String(o.id)); + } + } + const multi = Object.entries(byAddr) + .map(([addr, set]) => ({ addr, ops: [...set] })) + .filter((x) => x.ops.length > 1) + .sort((a, b) => b.ops.length - a.ops.length); + log('addresses controlling multiple operators (top 10):'); + for (const m of multi.slice(0, 10)) log(` ${m.addr} -> #${m.ops.join(', #')}`); + if (!flag('multi')) { + log('first 6 operators:'); + for (const o of ops.slice(0, 6)) log(` #${o.id} manager=${o.managerAddress}`); + } + await context.close(); +}; + +main().catch((e) => { console.error('[visual-verify] FAILED:', e.message); process.exit(1); }); diff --git a/.claude/skills/visual-verify/scripts/verify.mjs b/.claude/skills/visual-verify/scripts/verify.mjs new file mode 100644 index 000000000..6d6a3b1f5 --- /dev/null +++ b/.claude/skills/visual-verify/scripts/verify.mjs @@ -0,0 +1,170 @@ +#!/usr/bin/env node +// Open a route in the running app, connected as an address or operator, and screenshot it. +// Also captures page health (console errors, uncaught exceptions, failed + 4xx/5xx requests), so a +// page that LOOKS fine but is actually broken (e.g. serving 404 chunks) gets flagged, not just imaged. +// +// Examples: +// node scripts/verify.mjs --operator 4 --route / # dashboard as operator #4 (local CSM) +// node scripts/verify.mjs --operator 4 --role rewards --route /settings +// node scripts/verify.mjs --address 0xd8dA…96045 --route /keys +// node scripts/verify.mjs --url http://localhost:3001 --operator 2 # the CM instance +// node scripts/verify.mjs --url https://cm.testnet.fi --operator 5 # a remote testnet +// node scripts/verify.mjs --operator 4 --theme dark # dark mode +// node scripts/verify.mjs --operator 4 --viewport mobile # mobile layout +// node scripts/verify.mjs --operator 4 --json # machine-readable result on stdout +// node scripts/verify.mjs --operator 4 --selector '[data-testid="accountSectionHeader"]' # one element +// node scripts/verify.mjs --no-connect --route / # disconnected/welcome state, no wallet +// node scripts/verify.mjs --operator 12 --headed --keep-open # watch it live, leave open +// +// The module (csm/cm) and chain are auto-detected from whatever --url points at; override only if needed. +// Flags: --url | --operator N | --address 0x.. | --role manager|rewards|owner | --route /path +// --theme light|dark | --viewport mobile|tablet|desktop|WxH | --selector (shoot one element) +// --no-connect (capture without a wallet) | --out file.png +// --json (structured result to stdout; logs to stderr) | --chain 560048 | --module csm|cm +// --headed | --keep-open | --full +import { mkdirSync } from 'node:fs'; +import { dirname, isAbsolute, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { connectAs, readState, diagnosticsSummary, setQuietLogs, log } from './lib.mjs'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const SHOTS = join(HERE, '..', '.cache', 'shots'); + +const argv = process.argv.slice(2); +const flag = (name, def) => { + const i = argv.indexOf(`--${name}`); + return i === -1 ? def : argv[i + 1]; +}; +const has = (name) => argv.includes(`--${name}`); + +// On ANY failure, screenshot wherever we got stuck before reporting — a failure image (the modal that +// never opened, a blank card, the wrong page) is far more diagnostic than an error string alone. +const captureFailure = async (e, page, context, jsonMode) => { + let shot = null; + if (page) { + try { + mkdirSync(SHOTS, { recursive: true }); + shot = join(SHOTS, `FAILED-${Date.now()}.png`); + await page.screenshot({ path: shot }); + } catch { + shot = null; // a failure-screenshot failure must not mask the original error + } + } + if (context) await context.close().catch(() => {}); + if (jsonMode) { + process.stdout.write(JSON.stringify({ ok: false, error: e.message, screenshot: shot }) + '\n'); + } else { + console.error('[visual-verify] FAILED:', e.message); + if (shot) console.error('[visual-verify] failure screenshot ->', shot); + } + process.exit(1); +}; + +const main = async () => { + const operatorId = flag('operator'); + const address = flag('address'); + const noConnect = has('no-connect'); + const selector = flag('selector'); + const jsonMode = has('json'); + if (jsonMode) setQuietLogs(true); // keep stdout clean for the JSON payload + if (!noConnect && !operatorId && !address) { + console.error('Provide --operator or --address <0x…> (or --no-connect). See header of this file for examples.'); + process.exit(2); + } + const route = flag('route', '/'); + const headless = !has('headed'); + + // page/context are captured via onPage the instant they exist, so captureFailure can screenshot the + // exact failure point even if connectAs throws partway through (e.g. operator not found, modal hang). + let context, page; + try { + const conn = await connectAs({ + operatorId, + address, + role: flag('role', 'manager'), + origin: flag('url') || flag('origin'), // undefined -> lib default ($APP_ORIGIN / localhost:3000) + chainId: flag('chain') ? Number(flag('chain')) : undefined, // undefined -> auto-detect + module: flag('module'), // undefined -> auto-detect + route, + headless, + theme: flag('theme'), // light|dark, undefined -> app default + viewport: flag('viewport'), // mobile|tablet|desktop|WxH, undefined -> default + connect: !noConnect, // --no-connect -> capture the disconnected/welcome state + onPage: (p, c) => { + page = p; + context = c; + }, + }); + const { diagnostics, module, theme, viewport, origin, chainId, address: account, operator } = conn; + + // Resolve output path AFTER connecting so the default name can include the detected module + + // theme/viewport/selector variant — otherwise different variants would clobber each other. + let out = flag('out'); + if (out) { + if (!isAbsolute(out)) out = join(process.cwd(), out); + } else { + mkdirSync(SHOTS, { recursive: true }); + const who = noConnect ? 'disconnected' : operatorId ? `op${operatorId}-${flag('role', 'manager')}` : `addr-${address.slice(0, 8)}`; + const selSlug = selector ? 'el_' + selector.replace(/[^a-z0-9]+/gi, '').slice(0, 20) : ''; + const variant = [theme, viewport, selSlug].filter(Boolean).join('-'); + out = join(SHOTS, `${module}-${who}${route.replace(/[^a-z0-9]+/gi, '_')}${variant ? '-' + variant : ''}.png`); + } + + const state = await readState(page); + log('STATE', JSON.stringify(state)); + if (!noConnect && operatorId != null) { + const shown = (state.operator || '').match(/#(\d+)/)?.[1]; + log(shown === String(operatorId) ? `confirmed operator #${operatorId} is active` : `WARN: requested #${operatorId} but showing #${shown}`); + } + // --selector shoots a single element (scrolls it into view first); otherwise the page/viewport. + if (selector) { + const el = page.locator(selector).first(); + if (!(await el.isVisible({ timeout: 10000 }).catch(() => false))) { + throw new Error(`--selector "${selector}" matched no visible element on ${state.url}`); + } + await el.screenshot({ path: out }); + log(`screenshot (element ${selector}) ->`, out); + } else { + await page.screenshot({ path: out, fullPage: has('full') }); + log('screenshot ->', out); + } + + // Page-health report — flags broken-but-pretty pages (404 chunks, runtime errors, failed requests). + const health = diagnosticsSummary(diagnostics); + if (health.total === 0) { + log('page health: clean (no console/network errors)'); + } else { + const c = health.counts; + log(`page health: ${health.total} issue(s) — ${c.consoleErrors} console, ${c.pageErrors} pageerror, ${c.failedRequests} failed-req, ${c.httpErrors} HTTP 4xx/5xx`); + for (const er of diagnostics.pageErrors.slice(0, 10)) log(` pageerror: ${er}`); + for (const er of diagnostics.consoleErrors.slice(0, 10)) log(` console: ${er.text}`); + for (const r of diagnostics.httpErrors.slice(0, 10)) log(` HTTP ${r.status}: ${r.url}`); + for (const r of diagnostics.failedRequests.slice(0, 10)) log(` failed (${r.error}): ${r.url}`); + } + + if (jsonMode) { + // Single JSON object on stdout (logs were routed to stderr). `health.total > 0` is the + // machine-readable "this page has problems" signal even when the screenshot looks fine. + process.stdout.write( + JSON.stringify( + { ok: true, origin, module, chainId, theme: theme || null, viewport: viewport || null, route, connected: !noConnect, selector: selector || null, address: account, operator, screenshot: out, state, health, diagnostics }, + null, + 2, + ) + '\n', + ); + } + + if (has('keep-open')) { + log('--keep-open set; leaving browser open. Ctrl-C to exit.'); + await new Promise(() => {}); + } + await context.close(); + } catch (e) { + await captureFailure(e, page, context, jsonMode); + } +}; + +main().catch((e) => { + console.error('[visual-verify] FAILED:', e.message); + process.exit(1); +}); diff --git a/.env.example b/.env.example index 7acc7fe68..8a3ce4f8e 100644 --- a/.env.example +++ b/.env.example @@ -1,22 +1,23 @@ # RPC API urls by network # EL_RPC_URLS_{CHAIN_ID} list or URLs delimeted by commas, first entry is primary, else are fallbacks EL_RPC_URLS_1= -EL_RPC_URLS_17000= +EL_RPC_URLS_560048= # IPFS prefill RPC URLs - list of URLs delimited by commas PREFILL_UNSAFE_EL_RPC_URLS_1= -PREFILL_UNSAFE_EL_RPC_URLS_17000= +PREFILL_UNSAFE_EL_RPC_URLS_560048= # CL API urls by network # CL_API_URLS_{CHAIN_ID} list or URLs delimeted by commas, first entry is primary, else are fallbacks CL_API_URLS_1= -CL_API_URLS_17000= +CL_API_URLS_560048= # MAINTENANCE mode MAINTENANCE= -# supported networks for connecting wallet -SUPPORTED_CHAINS=1 +# Module type: CSM or Curated Moudle (csm|cm) +MODULE=csm +# DEVNET_ADDRESSES_FILE_PATH=../community-staking-module/artifacts/local/curated/deploy-hoodi.json # this chain uses when a wallet is not connected DEFAULT_CHAIN=1 @@ -44,5 +45,48 @@ WALLETCONNECT_PROJECT_ID= # ETH Stake Widget API for IPFS mode WIDGET_API_BASE_PATH_FOR_IPFS= -# Survey api -SURVEY_API=https://survey.testnet.fi +# EthSeer API +ETHSEER_API_URL=https://www.migalabs.io/api/eth/v1/beacon/consensus/lido/csm/unified_performance +ETHSEER_API_TOKEN= + +# CSM SDK API URLs +KEYS_API_URL= +FEES_MONITORING_API_URL= + +# IPFS gateways (comma-separated). Each entry may include a `{cid}` placeholder; +# otherwise CID is appended. Tried before the default public gateways. +IPFS_GATEWAYS= + +# Surveys API base URL. If set, overrides the hardcoded surveyApi in +# consts/external-links.ts (useful for self-hosted survey backends). +SURVEYS_API_URL= + +# -------- Environment variables for tests -------- + +# testnet, prod, staging, preview, local +STAND_TYPE= + +# Default wallet with node operator +WALLET_SECRET_PHRASE= +# Full empty wallet +EMPTY_SECRET_PHRASE= +# Wallet with empty node operator +EMPTY_NODE_SECRET_PHRASE= + +WALLET_PASSWORD= + +# RPC url directly +RPC_URL= + +# All credentianals for run tests on preview stand +PREVIEW_STAND_URL= +PREVIEW_STAND_LOGIN= +PREVIEW_STAND_PASSWORD= + +# Refuse CF blocks for tests +REFUSE_CF_BLOCK_NAME= +REFUSE_CF_BLOCK_VALUE= + +# Forked tests settings +USE_FORK= # true | false +JUST_DIR= # Example: /Users//community-staking-module diff --git a/.eslintignore b/.eslintignore index 55d8dacb0..87f1d0497 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,7 @@ # dependencies /node_modules /.pnp +/lido-csm-sdk # testing /coverage @@ -15,3 +16,6 @@ # generated /generated + +**/.browser_context** + diff --git a/.eslintrc.json b/.eslintrc.json index 0cc6fa65d..2e829d0cd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -42,6 +42,12 @@ { "checksVoidReturn": false } + ], + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": ["tests/**"] + } ] }, "settings": { diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9acf268e9..ef92236fb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,4 @@ * @lidofinance/community-staking .github @lidofinance/review-gh-workflows +tests/ @lidofinance/lido-qa +playwright.config.* @lidofinance/lido-qa diff --git a/.github/actions/notify-broken-tests/action.yml b/.github/actions/notify-broken-tests/action.yml new file mode 100644 index 000000000..2e02f134a --- /dev/null +++ b/.github/actions/notify-broken-tests/action.yml @@ -0,0 +1,66 @@ +name: 'Notify Slack about broken workflow' +description: 'Sends a Slack message that the test workflow is broken' + +inputs: + webhook-url: + description: 'Slack incoming webhook URL' + required: true + duty-tag: + description: 'Slack subteam ID to mention (optional)' + required: false + default: '' + test-tags: + description: 'Test tags value to include in the message' + required: false + default: '' + +runs: + using: 'composite' + steps: + - name: Send Slack notification + shell: bash + env: + SLACK_WEBHOOK_URL: ${{ inputs.webhook-url }} + SLACK_DUTY_TAG: ${{ inputs.duty-tag }} + TEST_TAGS: ${{ inputs.test-tags }} + GH_ACTION_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + if [ -z "$SLACK_WEBHOOK_URL" ]; then + echo "Skipping notification — no webhook URL configured" + exit 0 + fi + DUTY_TAG="" + if [ -n "$SLACK_DUTY_TAG" ]; then + DUTY_TAG=" " + fi + TAGS="" + if [ -n "$TEST_TAGS" ]; then + TAGS=" (t:${TEST_TAGS})" + fi + PAYLOAD=$(jq -n \ + --arg duty "$DUTY_TAG" \ + --arg url "$GH_ACTION_URL" \ + --arg tags "$TAGS" \ + '{ + text: "Attention. Test workflow is broken!", + blocks: [ + { + type: "section", + text: { + type: "mrkdwn", + text: (":rotating_light: " + $duty + "*Attention. Test workflow is broken!*" + $tags) + } + }, + { + type: "actions", + elements: [ + { + type: "button", + text: { type: "plain_text", text: "View run" }, + url: $url + } + ] + } + ] + }') + curl -X POST -H 'Content-type: application/json' --data "$PAYLOAD" "$SLACK_WEBHOOK_URL" diff --git a/.github/actions/setup-just/action.yml b/.github/actions/setup-just/action.yml new file mode 100644 index 000000000..3bde36452 --- /dev/null +++ b/.github/actions/setup-just/action.yml @@ -0,0 +1,34 @@ +name: 'Setup just' +description: 'Install the just command runner, cached in ~/.cargo/bin across runs' + +inputs: + version: + description: 'just version to install' + required: false + default: '1.24.0' + +runs: + using: composite + steps: + - name: Build cache params + id: cache + shell: bash + env: + CACHE_PATH: | + ~/.cargo/bin/ + KEY_INPUT: | + just:${{ inputs.version }} + run: | + echo "path=$CACHE_PATH" >> "$GITHUB_OUTPUT" + echo "$KEY_INPUT" | md5sum | awk '{print $1}' | xargs -I% echo "key=cargobin-%-${RUNNER_OS}" >> "$GITHUB_OUTPUT" + + - uses: actions/cache@v6 + id: get-cache + with: + path: ${{ steps.cache.outputs.path }} + key: ${{ steps.cache.outputs.key }} + + - name: Install just + if: steps.get-cache.outputs.cache-hit != 'true' + shell: bash + run: cargo install "just@${{ inputs.version }}" diff --git a/.github/workflows/build-push-harbor.yml b/.github/workflows/build-push-harbor.yml new file mode 100644 index 000000000..91ce4ec0a --- /dev/null +++ b/.github/workflows/build-push-harbor.yml @@ -0,0 +1,55 @@ +name: Build and push csm-widget to Harbor + +on: + workflow_dispatch: + push: + branches: + - develop + +permissions: + contents: read + +env: + APP: csm-widget + REGISTRY: registry.dev.k8s-dev.org + REPOSITORY: team-csm + REGISTRY_USER: robot$team-csm-rw + IMAGE_TAG: dev + +jobs: + build-and-push: + runs-on: ubuntu-22.04 + steps: + - name: Check out the repo + uses: actions/checkout@v7 + + - name: Generate build-info.json + env: + BRANCH: ${{ github.ref_name }} + COMMIT: ${{ github.sha }} + run: | + jq -n \ + --arg version "${BRANCH}:${COMMIT}" \ + --arg branch "$BRANCH" \ + --arg commit "$COMMIT" \ + '{version: $version, branch: $branch, commit: $commit}' \ + > build-info.json + cat build-info.json + + - name: Setup buildx + uses: docker/setup-buildx-action@v4.2.0 + + - name: Log in to Harbor + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ env.REGISTRY_USER }} + password: ${{ secrets.HARBOR_ROBOT_TOKEN }} + + - name: Build and push docker image + uses: docker/build-push-action@v7 + with: + context: . + push: true + tags: ${{ env.REGISTRY }}/${{ env.REPOSITORY }}/${{ env.APP }}:${{ env.IMAGE_TAG }} + builder: ${{ steps.buildx.outputs.name }} diff --git a/.github/workflows/ci-dev-cm.yml b/.github/workflows/ci-dev-cm.yml new file mode 100644 index 000000000..aa1c78aa9 --- /dev/null +++ b/.github/workflows/ci-dev-cm.yml @@ -0,0 +1,29 @@ +name: CI Dev CM Hoodi + +on: + workflow_dispatch: + push: + branches: + - develop-cm + paths-ignore: + - ".github/**" + +permissions: {} + +jobs: + # test: + # ... + + deploy: + runs-on: ubuntu-latest + # needs: test + name: Build and deploy + steps: + - name: Testnet deploy + uses: lidofinance/dispatch-workflow@v1 + env: + APP_ID: ${{ secrets.APP_ID }} + APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} + TARGET_REPO: "lidofinance/infra-mainnet" + TARGET_WORKFLOW: "deploy_hoodi_testnet_cm_widget.yaml" + TARGET: "develop-cm" diff --git a/.github/workflows/ci-dev.yml b/.github/workflows/ci-dev.yml index dfe72ff22..25e81cf3a 100644 --- a/.github/workflows/ci-dev.yml +++ b/.github/workflows/ci-dev.yml @@ -1,4 +1,4 @@ -name: CI Dev +name: CI Dev Hoodi on: workflow_dispatch: @@ -25,5 +25,5 @@ jobs: APP_ID: ${{ secrets.APP_ID }} APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} TARGET_REPO: "lidofinance/infra-mainnet" - TARGET_WORKFLOW: "deploy_testnet_csm_widget.yaml" + TARGET_WORKFLOW: "deploy_hoodi_testnet_csm_widget.yaml" TARGET: "develop" diff --git a/.github/workflows/ci-preview-demolish-cm.yml b/.github/workflows/ci-preview-demolish-cm.yml new file mode 100644 index 000000000..d6be4f48b --- /dev/null +++ b/.github/workflows/ci-preview-demolish-cm.yml @@ -0,0 +1,27 @@ +name: CI Preview stand demolish (CM) + +on: + workflow_dispatch: + pull_request: + types: + [converted_to_draft, closed] + branches: + - develop-cm + +permissions: {} + +jobs: + deploy: + runs-on: ubuntu-latest + name: Build and deploy + steps: + - name: Preview stand demolish (CM) + uses: lidofinance/dispatch-workflow@v1 + env: + APP_ID: ${{ secrets.APP_ID }} + APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} + TARGET_REPO: "lidofinance/infra-mainnet" + TARGET: ${{ github.head_ref }} + TARGET_WORKFLOW: "preview_stand_demolish.yaml" + INPUTS_REPO_NAME: "lidofinance/cm-widget" + INPUTS_PR_ID: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/ci-preview-demolish.yml b/.github/workflows/ci-preview-demolish.yml index 0056c15f2..c12e8386e 100644 --- a/.github/workflows/ci-preview-demolish.yml +++ b/.github/workflows/ci-preview-demolish.yml @@ -7,6 +7,7 @@ on: [converted_to_draft, closed] branches-ignore: - main + - develop-cm permissions: {} diff --git a/.github/workflows/ci-preview-deploy-cm.yml b/.github/workflows/ci-preview-deploy-cm.yml new file mode 100644 index 000000000..572bb7f51 --- /dev/null +++ b/.github/workflows/ci-preview-deploy-cm.yml @@ -0,0 +1,78 @@ +name: CI Preview stand deploy (CM) + +on: + workflow_dispatch: + inputs: + inventory: + description: inventory to be used for preview stand deploying + default: testnet + required: false + type: choice + options: + - staging + - testnet + + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + branches: + - develop-cm + +permissions: + contents: read + pull-requests: read + +jobs: + deploy: + runs-on: ubuntu-latest + if: ${{ github.event.pull_request.draft == false }} + name: Build and deploy + outputs: + stand_url: ${{ steps.stand.outputs.url }} + steps: + - uses: lidofinance/gh-find-current-pr@v1 + id: pr + + - name: Set ref + id: ref + run: echo "short_ref=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT + + - name: Preview stand deploying (CM) + uses: lidofinance/dispatch-workflow@v1 + env: + APP_ID: ${{ secrets.APP_ID }} + APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} + TARGET_REPO: "lidofinance/infra-mainnet" + TARGET: ${{ github.head_ref || steps.ref.outputs.short_ref }} + TARGET_WORKFLOW: "preview_stand_deploy.yaml" + INPUTS_REPO_NAME: "lidofinance/cm-widget" + INPUTS_PR_ID: ${{ github.event.pull_request.number || steps.pr.outputs.number }} + INPUTS_INVENTORY: "${{ inputs.inventory || 'testnet' }}" + + - name: Define repo short name (CM) + run: echo "short_name=$(echo ${{ github.repository }} | cut -d "/" -f 2)" >> $GITHUB_OUTPUT + id: repo + + - name: Define branch hash + run: echo "hash=$(echo "$HEAD_REF" | shasum -a 256 | cut -c -10)" >> $GITHUB_OUTPUT + id: branch + env: + HEAD_REF: ${{ github.head_ref || steps.ref.outputs.short_ref }} + + - name: Extract stand url + if: always() + run: echo "url=https://$SHORT_NAME-$BRANCH_HASH.branch-preview.org" >> $GITHUB_OUTPUT + id: stand + env: + SHORT_NAME: ${{ steps.repo.outputs.short_name }} + BRANCH_HASH: ${{ steps.branch.outputs.hash }} + + tests: + needs: deploy + if: ${{ github.event.pull_request.draft == false && inputs.inventory == 'testnet'}} + uses: ./.github/workflows/tests.yml + secrets: inherit + with: + preview_stand_url: ${{ needs.deploy.outputs.stand_url }} + stand_type: "preview" + tags: "smoke" + qase_plan_id: 5 # Smoke Preview Plan diff --git a/.github/workflows/ci-preview-deploy.yml b/.github/workflows/ci-preview-deploy.yml index f2bd30cec..0cee30ced 100644 --- a/.github/workflows/ci-preview-deploy.yml +++ b/.github/workflows/ci-preview-deploy.yml @@ -13,10 +13,10 @@ on: - testnet pull_request: - types: - [opened, synchronize, reopened, ready_for_review] + types: [opened, synchronize, reopened, ready_for_review] branches-ignore: - main + - develop-cm permissions: contents: read @@ -66,3 +66,14 @@ jobs: env: SHORT_NAME: ${{ steps.repo.outputs.short_name }} BRANCH_HASH: ${{ steps.branch.outputs.hash }} + + tests: + needs: deploy + if: ${{ github.event.pull_request.draft == false && (!inputs.inventory || inputs.inventory == 'testnet') }} + uses: ./.github/workflows/tests.yml + secrets: inherit + with: + preview_stand_url: ${{ needs.deploy.outputs.stand_url }} + stand_type: "preview" + tags: "smoke" + qase_plan_id: 5 # Smoke Preview Plan diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml new file mode 100644 index 000000000..dc9463687 --- /dev/null +++ b/.github/workflows/e2e-tests.yml @@ -0,0 +1,227 @@ +name: E2E Tests (reusable) + +# Reusable workflow that runs the CSM/CM Playwright e2e suite. +# +# Unlike a composite action (whose internal steps collapse into a single +# UI node), every step below shows up as its own top-level step in the run. +# Callers parameterise it through `inputs` and pass secrets via +# `secrets: inherit`. Fork-only setup is gated behind `use_fork`. + +on: + workflow_call: + inputs: + module: + description: "Module under test (csm | cm). Selects `yarn test::e2e`." + required: false + type: string + default: csm + use_fork: + description: "Run against a local fork (adds contract checkout + build steps)." + required: false + type: boolean + default: false + stand_type: + description: "Stand type (testnet | preview | staging | prod)." + required: false + type: string + default: testnet + test_tags: + description: "Playwright tag filter passed as TEST_TAGS." + required: false + type: string + default: "!forked" + qase_project_id: + description: "Qase project ID (CSM | CM)." + required: false + type: string + default: CSM + qase_plan_id: + description: "Qase plan ID (string; empty disables plan reporting)." + required: false + type: string + default: "" + timeout_minutes: + description: "Job timeout in minutes." + required: false + type: number + default: 90 + staking_modules_ref: + description: "staking-modules ref to checkout (fork only)." + required: false + type: string + default: main + deploy_config: + description: "DEPLOY_CONFIG path (fork only)." + required: false + type: string + default: "" + chain: + description: "CHAIN name (fork only)." + required: false + type: string + default: "" + artifacts_dir: + description: "ARTIFACTS_DIR path (fork only)." + required: false + type: string + default: "" + preview_stand_url: + description: "Preview stand url. When stand_type=preview it must be non-empty." + required: false + type: string + default: "" + preview_stand_env: + description: "Preview stand env." + required: false + type: string + default: "" + +jobs: + test: + name: Run e2e tests + runs-on: ubuntu-24.04 + timeout-minutes: ${{ inputs.timeout_minutes }} + env: + # Required envs + RPC_URL: ${{ secrets.RPC_URL }} + WALLET_SECRET_PHRASE: ${{ secrets.WALLET_SECRET_PHRASE }} + WALLET_PASSWORD: ${{ secrets.WALLET_PASSWORD }} + EMPTY_SECRET_PHRASE: ${{ secrets.EMPTY_SECRET_PHRASE }} + EMPTY_NODE_SECRET_PHRASE: ${{ secrets.EMPTY_NODE_SECRET_PHRASE }} + WC_PROJECT_ID: ${{ secrets.WC_PROJECT_ID }} + MODULE: ${{ inputs.module }} + STAND_TYPE: ${{ inputs.stand_type }} + + # Common envs + QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }} + QASE_PROJECT_ID: ${{ inputs.qase_project_id }} + QASE_PLAN_ID: ${{ inputs.qase_plan_id }} + GH_ACTION_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_BRANCH_REF_NAME: ${{ github.ref_name }} + GH_EVENT_NAME: ${{ github.event_name }} + NODE_OPTIONS: --max-old-space-size=4096 + TEST_TAGS: ${{ inputs.test_tags }} + REPORT_ENABLED: ${{ github.event_name == 'schedule' && 'true' || 'false' }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_DUTY_TAG: "S09H269H2TT" + ARTIFACT_PASSWORD: ${{ secrets.ARTIFACT_PASSWORD }} + + # Optional envs + REFUSE_CF_BLOCK_NAME: ${{ secrets.REFUSE_CF_BLOCK_NAME }} + REFUSE_CF_BLOCK_VALUE: ${{ secrets.REFUSE_CF_BLOCK_VALUE }} + PUSHGATEWAY_URL: ${{ secrets.PUSHGATEWAY_URL }} + PUSHGATEWAY_USERNAME: ${{ secrets.PUSHGATEWAY_USERNAME }} + PUSHGATEWAY_PASSWORD: ${{ secrets.PUSHGATEWAY_PASSWORD }} + GRAFANA_URL: ${{ secrets.GRAFANA_URL }} + GRAFANA_API_KEY: ${{ secrets.GRAFANA_API_KEY }} + PINATA_API_KEY: ${{ secrets.QA_PINATA_API_KEY }} + PINATA_API_SECRET: ${{ secrets.QA_PINATA_API_SECRET }} + + # Fork envs (ignored unless use_fork=true) + USE_FORK: ${{ inputs.use_fork }} + DEPLOY_CONFIG: ${{ inputs.deploy_config }} + CHAIN: ${{ inputs.chain }} + + steps: + - uses: actions/checkout@v7 + with: + ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: false + + - uses: actions/setup-node@v6 + with: + node-version: "24" + cache: "yarn" + + # --- Fork-only setup --- + - name: Checkout staking-modules + if: ${{ inputs.use_fork }} + uses: actions/checkout@v7 + with: + repository: lidofinance/staking-modules + path: staking-modules + ref: ${{ inputs.staking_modules_ref }} + + - name: Setup just + if: ${{ inputs.use_fork }} + uses: ./.github/actions/setup-just + + - name: Install Foundry + if: ${{ inputs.use_fork }} + uses: foundry-rs/foundry-toolchain@v1 + with: + version: v1.7.1 + + - name: Restore yarn cache + uses: actions/cache@v6 + with: + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }} + + - name: Install contracts dependencies + if: ${{ inputs.use_fork }} + run: cd staking-modules && yarn install --immutable + + - name: Build fork + if: ${{ inputs.use_fork }} + run: cd staking-modules && just deps && just build + + # --- Test run --- + - name: Install dependencies + run: yarn install --immutable + + - name: Install Playwright Browsers + run: yarn playwright install chromium --with-deps + + - name: Download keys generator binary + run: bash ./tests/scripts/set_up_keys_generator.sh + + - name: Set up preview-stand credentials + if: ${{ inputs.stand_type == 'preview' }} + run: | + if [ -n "${{ inputs.preview_stand_url }}" ]; then + echo "Setting login and password for preview stand" + echo "PREVIEW_STAND_LOGIN=${{ secrets.PREVIEW_STAND_LOGIN }}" >> $GITHUB_ENV + echo "PREVIEW_STAND_PASSWORD=${{ secrets.PREVIEW_STAND_PASSWORD }}" >> $GITHUB_ENV + echo "PREVIEW_STAND_URL=${{ inputs.preview_stand_url }}" >> $GITHUB_ENV + echo "PREVIEW_STAND_ENV=${{ inputs.preview_stand_env }}" >> $GITHUB_ENV + else + echo "PREVIEW_STAND_URL not provided for preview environment" + exit 1 + fi + + - name: Run tests + id: run-tests + run: | + echo -e "\033[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m" + echo -e "🚀 Running on Stand Type: \033[1;34m$STAND_TYPE\033[0m" + echo -e "🧪 Test Tags: \033[1;34m$TEST_TAGS\033[0m" + echo -e "🌱 Branch: \033[1;34m${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}\033[0m" + echo -e "🔗 Test Plan: \033[1;34m${QASE_PLAN_ID}\033[0m" + echo -e "\033[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m" + + xvfb-run --auto-servernum -- yarn test:${{ inputs.module }}:e2e + + - name: Encrypt Playwright report + if: always() + run: | + if [ -d playwright-report ]; then + tar -czf - playwright-report/ | openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -pass env:ARTIFACT_PASSWORD -out playwright-report.tar.gz.enc + fi + + - uses: actions/upload-artifact@v7 + if: always() + with: + name: playwright-report-${{ inputs.module }} + path: playwright-report.tar.gz.enc + retention-days: 1 + + - name: Notify Slack about broken workflow + if: always() && github.event_name == 'schedule' && (steps.run-tests.conclusion == 'skipped' || steps.run-tests.conclusion == 'cancelled') + uses: ./.github/actions/notify-broken-tests + env: + ARTIFACTS_DIR: ${{ inputs.artifacts_dir }} + with: + webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} + duty-tag: ${{ env.SLACK_DUTY_TAG }} + test-tags: ${{ env.TEST_TAGS }} diff --git a/.github/workflows/tests-fork-cm.yml b/.github/workflows/tests-fork-cm.yml new file mode 100644 index 000000000..e0d28338d --- /dev/null +++ b/.github/workflows/tests-fork-cm.yml @@ -0,0 +1,46 @@ +name: Forked Test CM-widget +run-name: Forked CM-widget Tests. Env [${{ github.event.inputs.stand_type || 'testnet' }}] + +on: + schedule: + - cron: "0 6 * * *" # Every day at 6 AM UTC + workflow_dispatch: + inputs: + stand_type: + description: "Stand type" + required: true + type: choice + default: testnet + options: + - testnet + - preview + preview_stand_url: + description: 'Preview stand url (only if "Stand type" is "preview")' + required: false + type: string + preview_stand_env: + description: 'Preview stand env (only if "Stand type" is "preview")' + required: false + type: choice + default: testnet + options: + - testnet + - infra + +jobs: + test: + name: CM widget (fork) + uses: ./.github/workflows/e2e-tests.yml + secrets: inherit + with: + module: cm + use_fork: true + stand_type: ${{ inputs.stand_type || github.event.inputs.stand_type || 'testnet' }} + test_tags: forked + qase_project_id: CM + staking_modules_ref: test/local-scripts + deploy_config: ./artifacts/hoodi/curated/deploy-hoodi.json + chain: hoodi + artifacts_dir: ./artifacts/hoodi/ + preview_stand_url: ${{ inputs.preview_stand_url || github.event.inputs.preview_stand_url || '' }} + preview_stand_env: ${{ github.event.inputs.preview_stand_env || '' }} diff --git a/.github/workflows/tests-fork.yml b/.github/workflows/tests-fork.yml new file mode 100644 index 000000000..068dae821 --- /dev/null +++ b/.github/workflows/tests-fork.yml @@ -0,0 +1,47 @@ +name: Forked Test CSM-widget +run-name: Forked CSM-widget Tests. Env [${{ github.event.inputs.stand_type || 'testnet' }}] + +on: + schedule: + - cron: "0 6 * * *" # Every day at 6 AM UTC + workflow_dispatch: + inputs: + stand_type: + description: "Stand type" + required: true + type: choice + default: testnet + options: + - testnet + - preview + preview_stand_url: + description: 'Preview stand url (only if "Stand type" is "preview")' + required: false + type: string + preview_stand_env: + description: 'Preview stand env (only if "Stand type" is "preview")' + required: false + type: choice + default: testnet + options: + - testnet + - infra + +jobs: + test: + name: CSM widget (fork) + uses: ./.github/workflows/e2e-tests.yml + secrets: inherit + with: + module: csm + use_fork: true + stand_type: ${{ inputs.stand_type || github.event.inputs.stand_type || 'testnet' }} + test_tags: forked + qase_project_id: CSM + qase_plan_id: "8" + staking_modules_ref: test/local-scripts + deploy_config: ./artifacts/hoodi/upgrade-v3-hoodi.json + chain: hoodi + artifacts_dir: ./artifacts/hoodi/ + preview_stand_url: ${{ inputs.preview_stand_url || github.event.inputs.preview_stand_url || '' }} + preview_stand_env: ${{ github.event.inputs.preview_stand_env || '' }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 000000000..079bcd947 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,73 @@ +name: Test CSM-widget +run-name: CSM-widget Tests. Env [${{ github.event.inputs.stand_type || 'testnet' }}] + +on: + schedule: + - cron: "0 6 * * *" # Every day at 6 AM UTC + workflow_dispatch: + inputs: + stand_type: + description: "Stand type" + required: true + type: choice + default: testnet + options: + - prod + - staging + - testnet + - preview + tags: + description: "Tags for running test suite" + required: false + type: choice + default: "-" + options: + - "-" + - smoke + - performTX + preview_stand_url: + description: 'Preview stand url (only if "Stand type" is "preview")' + required: false + type: string + preview_stand_env: + description: 'Preview stand env (only if "Stand type" is "preview")' + required: false + type: choice + default: testnet + options: + - testnet + - infra + + workflow_call: + inputs: + preview_stand_url: + required: true + type: string + description: Stand url + stand_type: + description: "Stand type" + required: true + type: string + tags: + required: false + type: string + default: "-" + description: "Test tags" + qase_plan_id: + required: false + type: number + description: "Qase Plan ID" + +jobs: + test: + name: CSM widget + uses: ./.github/workflows/e2e-tests.yml + secrets: inherit + with: + module: csm + stand_type: ${{ inputs.stand_type || github.event.inputs.stand_type || 'testnet' }} + test_tags: ${{ inputs.tags || github.event.inputs.tags || '!forked' }} + qase_project_id: CSM + qase_plan_id: ${{ inputs.qase_plan_id || (github.event_name == 'schedule' && '7') || '' }} + preview_stand_url: ${{ inputs.preview_stand_url || github.event.inputs.preview_stand_url || '' }} + preview_stand_env: ${{ github.event.inputs.preview_stand_env || '' }} diff --git a/.gitignore b/.gitignore index 0a71a893b..5716b8a44 100644 --- a/.gitignore +++ b/.gitignore @@ -12,12 +12,14 @@ tsconfig.tsbuildinfo /test-results/ /playwright-report/ /playwright/.cache/ +.playwright-mcp/ # testing /coverage # generated /generated +/modules/web3/generated.ts # next.js /.next/ @@ -28,11 +30,11 @@ tsconfig.tsbuildinfo # misc .DS_Store +dev-cm # env -.env.local -.env.production -.env.development +.env* +!.env.example # debug npm-debug.log* @@ -42,5 +44,15 @@ yarn-error.log* #ide .vscode .idea +.claude/* +!.claude/skills/ +.mcp.json +.qodo +**/.browser_context** /public/runtime/ +/public/manifest.json +/keys-generator-bin/ +deposit_data.json +local_fork_config.json +.walletPresets.state.json diff --git a/.husky/commit-msg b/.husky/commit-msg index d71a03b9f..2785bc1d2 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,4 +1 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - yarn commitlint --edit $1 diff --git a/.husky/pre-commit b/.husky/pre-commit index d2ae35e84..372362317 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - yarn lint-staged diff --git a/.nvmrc b/.nvmrc index 209e3ef4b..a45fd52cc 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20 +24 diff --git a/.prettierignore b/.prettierignore index b87ad4294..cec003233 100644 --- a/.prettierignore +++ b/.prettierignore @@ -13,3 +13,5 @@ /build CHANGELOG.md + +/.browser_context** diff --git a/APY.md b/APY.md new file mode 100644 index 000000000..7e36d5c6d --- /dev/null +++ b/APY.md @@ -0,0 +1,365 @@ +# APY Metrics Implementation Plan + +## Overview + +Implement APY (Annual Percentage Yield) display in the Bond & Rewards section, inspired by the third-party [lido-csm-dashboard](https://github.com/0xdespot/lido-csm-dashboard). This addresses community feedback for "single pane of glass" performance monitoring and helps operators validate their staking returns. + +## Current State + +### Existing Bond Section + +**File**: [features/dashboard/bond/bond-section.tsx](features/dashboard/bond/bond-section.tsx) + +Current components: + +- `` - Shows claimable amount (rewards + excess bond - locked) +- `` - Shows current bond vs required bond +- `` - Shows latest distribution frame with validator performance + +### Available Data Hooks + +**Location**: [modules/web3/hooks/](modules/web3/hooks/) + +- ✅ `useOperatorRewardsHistory()` - Returns array of `ValidatorRewardsEntity[]` with historical rewards +- ✅ `useOperatorLastRewards()` - Latest frame: distributed amount, validator counts, threshold +- ✅ `useOperatorBalance()` - Bond amounts (current, required, excess) +- ✅ `useFrameInfo()` - Frame timing (lastReport, frameDuration, nextDistribution) + +### ValidatorRewardsEntity Type + +From `@lidofinance/lido-csm-sdk`: + +```typescript +type ValidatorRewardsEntity = { + fee: bigint; // Reward amount for this frame + startTimestamp: number; // Frame start timestamp + endTimestamp: number; // Frame end timestamp + receivedRewards: bigint; // Total received + pubkey: Hex | undefined; + // ... other fields +}; +``` + +## APY Calculation Methodology + +### Reward APY Formula + +Based on third-party dashboard approach: + +``` +Reward APY = (rewards / bond) * (365 / frame_days) * 100 +``` + +Where: + +- `rewards` = distributed amount for frame (stETH) +- `bond` = required bond for frame (stETH) +- `frame_days` = (endTimestamp - startTimestamp) / 86400 +- Annualized by multiplying by `365 / frame_days` + +### Multi-Frame Views + +1. **Current Frame APY**: Using latest distribution data +2. **Previous Frame APY**: Using second-to-last distribution +3. **Lifetime APY**: Duration-weighted average across all frames + +For lifetime calculation: + +``` +Lifetime APY = Σ(frame_apy * frame_days) / total_days +``` + +This accounts for operators who increased validator counts over time, weighting each frame's APY by its duration. + +## Implementation Plan + +### Phase 1: Create APY Hook + +**New File**: `modules/web3/hooks/use-operator-apy.ts` + +**Purpose**: Calculate APY metrics from rewards history + +**Implementation**: + +```typescript +export const useOperatorApy = (nodeOperatorId: NodeOperatorId | undefined) => { + const { data: rewardsHistory } = useOperatorRewardsHistory(nodeOperatorId); + const { data: balance } = useOperatorBalance(nodeOperatorId); + + return useQuery({ + queryKey: ['operator-apy', { nodeOperatorId }], + enabled: !!rewardsHistory && !!balance, + queryFn: () => { + const frames = groupRewardsByFrame(rewardsHistory); + + // Calculate APY for each frame + const currentFrameApy = calculateFrameApy(frames[0], balance.required); + const previousFrameApy = calculateFrameApy(frames[1], balance.required); + const lifetimeApy = calculateLifetimeApy(frames, balance.required); + + return { + current: currentFrameApy, + previous: previousFrameApy, + lifetime: lifetimeApy, + change: currentFrameApy - previousFrameApy, // For trend display + }; + }, + }); +}; +``` + +**Helper Functions**: + +- `groupRewardsByFrame()` - Group `ValidatorRewardsEntity[]` by frame (using timestamps) +- `calculateFrameApy()` - Calculate single frame APY using formula above +- `calculateLifetimeApy()` - Duration-weighted average across all frames + +### Phase 2: Create APY Component + +**New File**: `features/dashboard/bond/apy-metrics.tsx` + +**Purpose**: Display APY metrics with tooltips + +**UI Design**: + +``` +┌─────────────────────────────────────┐ +│ APY Metrics [?] │ +├─────────────────────────────────────┤ +│ Current Frame 5.2% ↑ 0.3% │ +│ Previous Frame 4.9% │ +│ Lifetime Average 5.1% │ +└─────────────────────────────────────┘ +``` + +**Features**: + +- Tooltip on [?] explaining APY calculation +- Trend indicator (↑/↓) comparing current vs previous +- Color coding: green for positive change, red for negative +- Loading states while data fetches +- Handle edge cases: no history, single frame, zero bond + +**Component Structure**: + +```typescript +export const ApyMetrics: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: apy, isPending } = useOperatorApy(nodeOperatorId); + + return ( + } + > + + + + + + + ); +}; +``` + +### Phase 3: Integrate into Bond Section + +**Modified File**: `features/dashboard/bond/bond-section.tsx` + +**Changes**: + +```typescript +import { ApyMetrics } from './apy-metrics'; + +export const BondSection: FC = () => { + return ( + + + + + {/* NEW */} + + + + ); +}; +``` + +Position between `` and `` for logical flow: bond status → APY performance → detailed rewards. + +### Phase 4: Add Matomo Tracking + +**Modified File**: `consts/matomo-click-events.ts` + +Add event types: + +- `apyMetricsExpanded` - Track accordion expansion +- `apyMetricsTooltipViewed` - Track tooltip interactions + +### Phase 5: Export Hook from Index + +**Modified File**: `modules/web3/hooks/index.ts` + +Add: + +```typescript +export { useOperatorApy } from './use-operator-apy'; +``` + +## Files to Create + +1. `modules/web3/hooks/use-operator-apy.ts` - APY calculation hook +2. `features/dashboard/bond/apy-metrics.tsx` - APY display component + +## Files to Modify + +1. `features/dashboard/bond/bond-section.tsx` - Add `` component +2. `modules/web3/hooks/index.ts` - Export new hook +3. `consts/matomo-click-events.ts` - Add tracking events (optional) + +## Edge Cases & Error Handling + +### No Rewards History + +- Display "No rewards data yet" with helper text +- Show once operator has at least one distribution + +### Single Frame Only + +- Show only "Current Frame APY" +- Hide previous and lifetime (or show N/A) + +### Zero Bond Requirement + +- APY calculation would divide by zero +- Display "—" or "N/A" with tooltip explaining bond requirement needed + +### Very High APY (>100%) + +- Can occur with small bond and large rewards +- Cap display at reasonable maximum or show as ">100%" + +### Negative Rewards + +- Possible if operator had MEV stealing penalties +- Handle gracefully, show negative APY or "Penalties applied" + +## Verification Plan + +### Unit Tests + +**New File**: `modules/web3/hooks/use-operator-apy.test.ts` + +Test scenarios: + +1. Calculate APY for single frame correctly +2. Calculate lifetime APY with multiple frames +3. Handle empty rewards history +4. Handle zero bond requirement +5. Verify duration weighting in lifetime calculation + +### Integration Tests + +**New File**: `features/dashboard/bond/apy-metrics.test.tsx` + +Test scenarios: + +1. Component renders with loading state +2. Component displays APY values correctly +3. Trend indicator shows up/down correctly +4. Tooltip displays and explains calculation +5. Accordion expands/collapses + +### E2E Tests + +**Modified File**: `tests/widget/operatorWithValidator/dashboard/bondRewards/apy.spec.ts` (new) + +Test scenarios: + +1. Navigate to dashboard +2. Verify APY Metrics section visible +3. Expand accordion +4. Verify current/previous/lifetime values displayed +5. Compare calculated values with expected (using test operator data) + +### Manual Testing Checklist + +1. **With test operator**: + + - View APY metrics on dashboard + - Verify values match manual calculation + - Check tooltip explanations + - Test accordion interaction + +2. **With different operator types**: + + - New operator (no history) - graceful empty state + - Single frame operator - shows current only + - Multi-frame operator - shows all three values + - Operator with varying bond - duration-weighted correctly + +3. **Performance**: + + - Dashboard loads without delay + - APY calculation doesn't block rendering + - React Query caching works (no refetch on navigate back) + +4. **Responsive design**: + - Mobile view (< 768px) + - Tablet view (768-1024px) + - Desktop view (> 1024px) + +## Success Criteria + +1. ✅ APY values match third-party dashboard calculations (within 0.1%) +2. ✅ Component follows existing design patterns (`AccordionStyle`, `TextBlock`, etc.) +3. ✅ Loading states and error handling consistent with other bond components +4. ✅ Tooltip provides clear explanation of APY calculation +5. ✅ No performance regression on dashboard load +6. ✅ Works across all operator types and edge cases +7. ✅ Matomo tracking captures user interactions + +## Future Enhancements (Out of Scope) + +Not included in this initial implementation: + +- **Bond APY**: Requires stETH rebase rate data (may need The Graph integration) +- **Net APY**: Combined reward + bond APY +- **APY Chart**: Historical APY trend visualization +- **Distribution History Table**: Detailed frame-by-frame breakdown +- **Claim History**: Transaction timeline of claims/withdrawals + +These can be added iteratively based on user feedback. + +## Technical Notes + +### Why Duration-Weighted Lifetime APY? + +Operators may start with 1 validator and grow to 10+ over time. Simple averaging would over-weight early low-balance periods. Duration weighting ensures recent performance with larger bond has appropriate influence on lifetime metrics. + +### Why Not Bond APY Initially? + +stETH rebasing is constant across all operators and doesn't differentiate operator performance. Reward APY is the operator-specific metric. Bond APY can be added later using current stETH APR (available from Lido API or The Graph). + +### Performance Considerations + +- `useOperatorRewardsHistory()` may return large arrays (100+ frames for early operators) +- Calculate APY in `queryFn` so React Query caches result +- Consider `useMemo` for expensive calculations if needed +- Grouping by frame reduces per-validator iteration + +## Comparison with Third-Party Tool + +### Similarities + +- Reward APY calculation formula +- Duration-weighted lifetime average +- Multi-timeframe view (current/previous/lifetime) + +### Differences + +- **Not implementing Bond APY**: Requires external rebase data +- **Not implementing Net APY**: Composite of Reward + Bond +- **UI Integration**: Embedded in dashboard vs standalone tool +- **Real-time Updates**: React Query auto-refresh vs CLI/manual + +This scoped approach delivers core operator value (performance visibility) while staying within existing data sources and UI patterns. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..85856b5fc --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,293 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Development Commands + +- **Development server**: `yarn dev` - Starts Next.js development server on +- **Build**: `yarn build` - Builds production bundle +- **Production server**: `yarn start` - Starts production server (requires build first) +- **Lint**: `yarn lint` - Runs ESLint on TypeScript files +- **Lint fix**: `yarn lint:fix` - Runs ESLint with auto-fix +- **Type check**: `yarn types` - Runs TypeScript compiler type checking +- **E2E tests**: `yarn test:csm:e2e` (CSM) or `yarn test:cm:e2e` (CM) - Runs Playwright e2e tests; append `:ui` (`test:csm:ui` / `test:cm:ui`) for interactive mode +- **Unit tests**: `yarn test:unit` - Runs Jest unit tests +- **Test setup**: `yarn test:setup` - Installs Chromium, keys generator, and Foundry fork tooling + +## Environment Setup + +The project requires an `.env.local` file with environment variables. Copy from `.env.example` and configure: + +- `MODULE` - Set to `csm` (default) or `cm` to choose the module version +- RPC provider URLs and CL API URLs with keys +- For testing, also set `STAND_TYPE`, `WALLET_SECRET_PHRASE`, `WALLET_PASSWORD` + +Install Playwright browser for tests: `yarn playwright install chromium --with-deps` + +## Architecture Overview + +This is a Next.js React application for Lido's Community Staking Module (CSM) widget, built on the Lido Frontend Template. + +### Module Versions + +**IMPORTANT**: This application has two distinct versions that share the same codebase: + +- **CSM (Community Staking Module)** - Fully implemented and production-ready +- **CM (Curated Module v2)** - Currently in development + +#### Configuration + +The active version is controlled by the `MODULE` environment variable: + +- Set `MODULE=csm` (default) for Community Staking Module +- Set `MODULE=cm` for Curated Module + +The module value is: + +1. Read from `process.env.MODULE` in `next.config.mjs` (uppercased to `moduleMode`) +2. Exposed via `publicRuntimeConfig.module`, then mapped to the `MODULE_NAME` enum in `config/get-preconfig.ts` +3. Accessible throughout the app via `useConfig()` hook: `config.module` + +#### Detecting Module Version in Code + +**Config-based detection:** + +```typescript +import { useConfig } from 'config'; + +const { + config: { module }, +} = useConfig(); +// module === 'CSM' or 'CM' (MODULE_NAME enum values, uppercase) +``` + +**Show Rules (for conditional rendering):** + +Use the `useShowRule` hook with `IS_CSM` or `IS_CM` rules: + +```typescript +import { useShowRule } from 'shared/hooks'; + +const check = useShowRule(); +if (check('IS_CSM')) { + // CSM-specific logic +} +``` + +Show rules can be applied to: + +- Navigation items (see `shared/layout/navigation/use-nav-items.tsx`) +- Page components +- Feature flags +- Any conditional UI rendering + +**Gates (CM-specific):** + +For CM module, gates control operator access levels: + +- Retrieved via `useAvailableGates` hook +- Gate types: `curated`, `permissioned`, `permissionless` +- Each gate has an ID, name, and curveId +- Used in CM operator registration flow + +#### Module-Specific Features + +Each module version has its own set of features and pages. The module type determines: + +- Available navigation routes +- Feature accessibility +- UI components and workflows specific to that module type +- Permission gates (CM only) + +Module constants and titles are defined in `consts/module.ts`. + +### Key Technologies + +- **Next.js 12** with Pages Router (not App Router) +- **React 18** with TypeScript +- **Styled Components** for styling +- **Wagmi v3** + **Reef-Knot** for Web3 wallet connections +- **Lido SDKs** (`@lidofinance/lido-csm-sdk`, `@lidofinance/lido-ethereum-sdk`) +- **React Query** for data fetching +- **React Hook Form** for form management +- **viem** for blockchain interactions + +### Project Structure + +#### Core Directories + +- **`features/`** - Main feature modules (dashboard, add-bond, add-keys, etc.) +- **`shared/`** - Reusable components, hooks, utilities +- **`modules/web3/`** - Web3 provider setup and blockchain hooks +- **`config/`** - Configuration management with feature flags +- **`consts/`** - Application constants and mappings +- **`pages/`** - Next.js pages and API routes + +#### Key Architecture Patterns + +**Feature-Based Structure**: Each feature in `features/` contains its page component, form logic, and feature-specific components. + +**Web3 Integration**: + +- `modules/web3/web3-provider/` - Wagmi + Reef-Knot wallet provider setup +- `modules/web3/hooks/` - Custom hooks for blockchain data (balances, operator info, etc.) +- `modules/web3/operator-provider/` - Node operator context and state management + +**SDK Access:** + +Use `useSmSDK()` hook to access Lido SDK instances: + +- `useSmSDK()` - Returns module-agnostic SDK (CSM or CM based on MODULE env var) +- `useSmSDK(MODULE.CSM)` - Returns CSM-specific SDK with type safety +- `useSmSDK(MODULE.CM)` - Returns CM-specific SDK with type safety + +Note: "SM" = Staking Module (module-agnostic terminology for code shared between CSM and CM). + +**Configuration System**: + +- Runtime configuration with server/public configs in `next.config.mjs` +- Feature flags in `config/feature-flags/` +- User configuration in `config/user-config/` + +**Shared Components**: + +- `shared/components/` - Reusable UI components +- `shared/hook-form/` - Form controls and validation utilities +- `shared/layout/` - Navigation, header, footer components + +### Development Notes + +- Uses **publicRuntimeConfig** for environment variables to support Docker deployment +- Includes bundle analysis with `ANALYZE_BUNDLE=true yarn build` +- Has automatic versioning using conventional commits +- Uses Playwright for e2e testing with wallet extensions + +### Form Architecture + +Forms follow a layered provider pattern documented in `shared/hook-form/README.md`: + +``` +DataProvider → FormProvider → FormControllerProvider → Form → FormLoader → Controls +``` + +Each form lives in `features/{feature}/{form-name}/` with a standard file structure: + +- `context/types.ts` — `*FormInputType` (form fields) and `*FormNetworkData` (blockchain data) +- `context/{form}-data-provider.tsx` — Network data fetching via React Query +- `context/{form}-provider.tsx` — React Hook Form setup with validation + submission +- `context/use-{form}-default-values.ts` — Initial values from network data +- `context/use-{form}-validation.ts` — Validation using `useFormValidation()` + `ValidationError` +- `context/use-{form}-submit.ts` — Transaction submission (`FormSubmitterHook` pattern) +- `context/{form}-updater.tsx` — Optional cross-field revalidation +- `controls/` — Form input components +- Custom `*FormLoader` — Permission-based rendering (show `` for read-only, full form for authorized users) + +### Show Rules + +`useShowRule` from `shared/hooks` powers conditional rendering based on module, wallet, and operator state: + +- Module: `IS_CSM`, `IS_CM` +- Wallet: `IS_CONNECTED_WALLET`, `IS_MAINNET` +- Operator: `IS_NODE_OPERATOR`, `NOT_NODE_OPERATOR`, `HAS_MANAGER_ROLE`, `HAS_REWARDS_ROLE`, `HAS_OWNER_ROLE` +- Features: `HAS_LOCKED_BOND`, `CAN_CREATE`, `CAN_CLAIM_ICS` + +Used in navigation items (`use-nav-items.tsx`), page guards, and conditional UI. + +## Code Style + +**IMPORTANT**: Follow these rules when writing code: + +- Always use `type` instead of `interface` for TypeScript type definitions +- Use function expressions only (`func-style: expression`) — no function declarations +- No `console.log` — only `console.warn`, `console.error`, `console.info`, `console.debug` +- Prefix unused variables with `_` (e.g., `_unused`) +- Respect `.editorconfig` (2-space indent) and `.prettierrc` (single quotes, trailing commas) +- Run `yarn lint:fix` after changes + +## Commit Conventions + +- Conventional commits required: `fix:`, `feat:`, `chore:`, etc. +- Enforced by commitlint + husky pre-commit hooks + +## Figma Design + +- When implementing UI from Figma designs, always use **exact texts** from the design. Do not rephrase, rewrite, or improvise copy — use the precise wording as shown in the Figma mockup. + +## Copy & Text + +- UI prose punctuation depends on sentence count: a single sentence has **no trailing dot**; two or more sentences end with a dot. Applies to descriptive copy — tooltips, descriptions, helper text, info/warning banners, error and toast messages — not button labels, titles, or short headings. +- Only the trailing **dot** is governed: leave `?`, `!`, and `…` as-is. Commas, semicolons, abbreviations (e.g., etc.), decimals, and URLs do not split a sentence. +- Examples: `"…Increases daily."` (2 sentences → dot); `"…part of your Excess Bond"` (1 sentence → no dot). + +## Testing + +### PageObject rules + +- Tests, pages, and components must always use the correct PageObject +- All locators must reference the component's `data-testid` +- If an element has no `data-testid`, add one — but only where it makes logical sense +- All `data-testid` values must be in camelCase +- Always start from fixtures and build on them + +### Test structure + +- Test names follow the `"should ... when ..."` pattern +- Each test must cover the UI comprehensively — don't write a test that makes only one assertion +- Always use `test.step` to structure assertions +- Always use fixtures + +### Test name style + +Names must be **very short** — the `describe` block already provides state context, the test name should only say what it checks. + +- Bad: `'Should show correct stETH amount, enable claim button and show "will receive" info when "Claim All" is selected'` +- Bad: `'Should show correct stETH amount and "will receive" info when "Claim All" selected'` +- Good: `'Should show correct stETH and "will receive" when "Claim All" selected'` +- Good: `'Should show SDK amounts on balance cards'` +- Good: `'Should disable "Excess Bond" option when all excess locked'` + +Rules: + +- Don't repeat the describe context (state/condition) in the test name +- Don't list every assertion — name the main thing being verified +- Drop filler: "and show success modal", "with correct", "option is" → "option", "is selected" → "selected", "is active" → "active", "info icon" → drop +- `when X` at the end is ok only if it adds info not already in describe + +### Amount assertions + +- **Never** use `not.toContainText('0.0 stETH')` or similar non-zero UI checks +- Compare against SDK values: `cmSDK.operator.getBondBalance(BigInt(noId))` → `.delta`, `cmSDK.getRewards(noId)` → `.available`, convert with `formatEther()` +- When SDK isn't available, use regex: `await expect(element).toContainText(/\d+\.\d+/)` +- Tolerance depends on display precision: + - Balance cards (display `X.X` — 1 decimal): `Math.abs(parseFloat(text) - expected) < 0.1` + - Form info / token selector (display 4 decimals): `Math.abs(parseFloat(text) - expected) < 0.0002` + +### Fork test pattern + +```typescript +let snapshotId: string; +let noId: number; // at describe scope when multiple tests need it + +test.beforeAll(async ({ cmSDK, forkActionService, widgetService }) => { + snapshotId = await cmSDK.evmSnapshot(); + await widgetService.somePage.open(); + noId = await widgetService.extractNodeOperatorId(); // must be before fork actions + await forkActionService.someSetup(noId, ...); + await widgetService.somePage.open(); // reopen to reflect new chain state +}); + +test.afterAll(async ({ cmSDK }) => { + await cmSDK.evmRevert(snapshotId); +}); +``` + +Use `beforeAll`/`afterAll` (one snapshot per describe), not `beforeEach`/`afterEach`. + +### Claim option constants + +Always import from the shared file — never inline raw strings: + +```typescript +import { CLAIM_OPTION } from './claim.const'; +// CLAIM_OPTION.ALL_TO_RA | CLAIM_OPTION.BOND_TO_RA | CLAIM_OPTION.REWARDS_TO_BOND +``` diff --git a/Dockerfile b/Dockerfile index 9b66c0812..f8f407f7d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # build env -FROM node:20-alpine as build +FROM node:24-alpine as build WORKDIR /app @@ -11,17 +11,17 @@ COPY . . RUN NODE_NO_BUILD_DYNAMICS=true yarn typechain && yarn build # public/runtime is used to inject runtime vars; it should exist and user node should have write access there for it RUN rm -rf /app/public/runtime && mkdir /app/public/runtime && chown node /app/public/runtime +# public/manifest.json is rewritten at server start based on MODULE; user node needs write access +RUN chown node /app/public/manifest.json # final image -FROM node:20-alpine as base +FROM node:24-alpine as base ARG BASE_PATH="" -ARG SUPPORTED_CHAINS="1" ARG DEFAULT_CHAIN="1" ENV NEXT_TELEMETRY_DISABLED=1 \ BASE_PATH=$BASE_PATH \ - SUPPORTED_CHAINS=$SUPPORTED_CHAINS \ DEFAULT_CHAIN=$DEFAULT_CHAIN WORKDIR /app diff --git a/README.md b/README.md index b66ad5ce2..7903ef420 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ More on CSM in the [docs](https://docs.lido.fi/staking-modules/csm/intro). ## Prerequisites -- Node.js v20+ +- Node.js v24 (`>=24.0.0 <25.0.0`) - Yarn package manager v1 This project requires an `.env` file which is distributed via private communication channels. A sample can be found in `.env.example` @@ -39,7 +39,7 @@ Step 5. Open [http://localhost:3000](http://localhost:3000) with your browser to ### Environment variables -This project uses `publicRuntimeConfig` in the [next.config.js](./next.config.js) and `getServerSideProps` on the pages (function may be empty, but it forces Next.js to switch to Server-Side Rendering mode). This is necessary to quickly start the docker container without rebuilding the application. +This project uses `publicRuntimeConfig` in the [next.config.mjs](./next.config.mjs) and `getServerSideProps` on the pages (function may be empty, but it forces Next.js to switch to Server-Side Rendering mode). This is necessary to quickly start the docker container without rebuilding the application. Read more about [runtime configuration](https://nextjs.org/docs/api-reference/next.config.js/runtime-configuration) and [automatic static optimization](https://nextjs.org/docs/advanced-features/automatic-static-optimization) @@ -60,6 +60,36 @@ git commit -m "feat: dark theme" yarn build && yarn start ``` +## Running Tests + +Before running the test suite, create a file named `.env.local` in the project root and populate it with the following variables: + +```dotenv +# Choose one: testnet, prod, staging, preview +STAND_TYPE=testnet + +# Wallet environment +WALLET_SECRET_PHRASE= +WALLET_PASSWORD= +``` + +Replace each value as needed for your environment. + +Install browser: + +```sh +yarn playwright install chromium --with-deps +``` + +To execute the tests, run the suite for the module you want: + +```sh +yarn test:csm:e2e # CSM widget +yarn test:cm:e2e # CM widget +``` + +Append `:ui` (`yarn test:csm:ui` / `yarn test:cm:ui`) to run Playwright in interactive UI mode. This loads your `.env.local` file and runs the configured test scripts. + ## Release flow To create a new release: diff --git a/TODO.md b/TODO.md new file mode 100644 index 000000000..99bdc0d51 --- /dev/null +++ b/TODO.md @@ -0,0 +1,41 @@ +# TODO + +[ ] use csm-sdk accounting to convert steth <-> wsteth +[ ] optimisations from 'calculator' branch + +[ ] mobile version remove terms modal +[ ] form's invalidation should refetch all + +## SDK + +[ ] drop CommonJS output - keep only ESM +[ ] cleanup accounting-sdk + +## other + +[ ] error on /api/performance +[_] pass keys-api from env + +[x] GPL3 everywhere + +## UI + +[x] legal disclaimer - make it stick to bottom + +## rewards-history + +[ ] disclaimer +[ ] filters +[x] year + +## CLAIMER role + +[ ] load list of operators for claim +[ ] show form to claim rewards + +## CLAIM BOND + +[ ] update styles + +[ ] bond debt +[ ] pending splits diff --git a/abi/CSAccounting.json b/abi/CSAccounting.json deleted file mode 100644 index 9251e63f3..000000000 --- a/abi/CSAccounting.json +++ /dev/null @@ -1,2293 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "lidoLocator", - "type": "address", - "internalType": "address" - }, - { - "name": "communityStakingModule", - "type": "address", - "internalType": "address" - }, - { - "name": "maxCurveLength", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "minBondLockRetentionPeriod", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "maxBondLockRetentionPeriod", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "ACCOUNTING_MANAGER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "CSM", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSModule" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "DEFAULT_BOND_CURVE_ID", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "LIDO", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ILido" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "LIDO_LOCATOR", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ILidoLocator" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MANAGE_BOND_CURVES_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MAX_BOND_LOCK_RETENTION_PERIOD", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MAX_CURVE_LENGTH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MIN_BOND_LOCK_RETENTION_PERIOD", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MIN_CURVE_LENGTH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_INFINITELY", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RECOVERER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RESET_BOND_CURVE_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RESUME_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "SET_BOND_CURVE_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "WITHDRAWAL_QUEUE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract IWithdrawalQueue" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "WSTETH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract IWstETH" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "addBondCurve", - "inputs": [ - { - "name": "bondCurve", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "outputs": [ - { - "name": "id", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "chargeFee", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "chargePenaltyRecipient", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "claimRewardsStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsUnstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stEthAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "wstETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "compensateLockedBondETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "depositETH", - "inputs": [ - { - "name": "from", - "type": "address", - "internalType": "address" - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "depositStETH", - "inputs": [ - { - "name": "from", - "type": "address", - "internalType": "address" - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "depositWstETH", - "inputs": [ - { - "name": "from", - "type": "address", - "internalType": "address" - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "wstETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "feeDistributor", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSFeeDistributor" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getActualLockedBond", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBond", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondAmountByKeysCount", - "inputs": [ - { - "name": "keys", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curve", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "pure" - }, - { - "type": "function", - "name": "getBondAmountByKeysCount", - "inputs": [ - { - "name": "keys", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondAmountByKeysCountWstETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondAmountByKeysCountWstETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curve", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondCurve", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondCurveId", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondLockRetentionPeriod", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondShares", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondSummary", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "current", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "required", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondSummaryShares", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "current", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "required", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getCurveInfo", - "inputs": [ - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getKeysCountByBondAmount", - "inputs": [ - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curve", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "pure" - }, - { - "type": "function", - "name": "getKeysCountByBondAmount", - "inputs": [ - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getLockedBondInfo", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct ICSBondLock.BondLock", - "components": [ - { - "name": "amount", - "type": "uint128", - "internalType": "uint128" - }, - { - "name": "retentionUntil", - "type": "uint128", - "internalType": "uint128" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRequiredBondForNextKeys", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "additionalKeys", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRequiredBondForNextKeysWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "additionalKeys", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getResumeSinceTimestamp", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMember", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMemberCount", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getUnbondedKeysCount", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getUnbondedKeysCountToEject", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "initialize", - "inputs": [ - { - "name": "bondCurve", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "admin", - "type": "address", - "internalType": "address" - }, - { - "name": "_feeDistributor", - "type": "address", - "internalType": "address" - }, - { - "name": "bondLockRetentionPeriod", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "_chargePenaltyRecipient", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "isPaused", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "lockBondETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "pauseFor", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "penalize", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "pullFeeRewards", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC1155", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC20", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC721", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverEther", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverStETHShares", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "releaseLockedBondETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renewBurnerAllowance", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resetBondCurve", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resume", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setBondCurve", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setChargePenaltyRecipient", - "inputs": [ - { - "name": "_chargePenaltyRecipient", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setLockedBondRetentionPeriod", - "inputs": [ - { - "name": "retention", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "settleLockedBondETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "totalBondShares", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "updateBondCurve", - "inputs": [ - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "bondCurve", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "event", - "name": "BondBurned", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "toBurnAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "burnedAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondCharged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "toChargeAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "chargedAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondClaimedStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "to", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondClaimedUnstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "to", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "requestId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondClaimedWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "to", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondCurveAdded", - "inputs": [ - { - "name": "bondCurve", - "type": "uint256[]", - "indexed": false, - "internalType": "uint256[]" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondCurveSet", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondCurveUpdated", - "inputs": [ - { - "name": "curveId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "bondCurve", - "type": "uint256[]", - "indexed": false, - "internalType": "uint256[]" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondDepositedETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "from", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondDepositedStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "from", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondDepositedWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "from", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondLockChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "newAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "retentionUntil", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondLockCompensated", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondLockRemoved", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondLockRetentionPeriodChanged", - "inputs": [ - { - "name": "retentionPeriod", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ChargePenaltyRecipientSet", - "inputs": [ - { - "name": "chargePenaltyRecipient", - "type": "address", - "indexed": false, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC1155Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC20Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC721Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "EtherRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Initialized", - "inputs": [ - { - "name": "version", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Paused", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Resumed", - "inputs": [], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StETHSharesRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "ElRewardsVaultReceiveFailed", - "inputs": [] - }, - { - "type": "error", - "name": "FailedToSendEther", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondCurveId", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondCurveLength", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondCurveMaxLength", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondCurveValues", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondLockAmount", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondLockRetentionPeriod", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialisationCurveId", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialization", - "inputs": [] - }, - { - "type": "error", - "name": "NodeOperatorDoesNotExist", - "inputs": [] - }, - { - "type": "error", - "name": "NotAllowedToRecover", - "inputs": [] - }, - { - "type": "error", - "name": "NotInitializing", - "inputs": [] - }, - { - "type": "error", - "name": "NothingToClaim", - "inputs": [] - }, - { - "type": "error", - "name": "PauseUntilMustBeInFuture", - "inputs": [] - }, - { - "type": "error", - "name": "PausedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "ResumedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "SafeCastOverflowedUintDowncast", - "inputs": [ - { - "name": "bits", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "SenderIsNotCSM", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAdminAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroChargePenaltyRecipientAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroFeeDistributorAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroLocatorAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroModuleAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroPauseDuration", - "inputs": [] - } -] diff --git a/abi/CSEarlyAdoption.json b/abi/CSEarlyAdoption.json deleted file mode 100644 index 87952339b..000000000 --- a/abi/CSEarlyAdoption.json +++ /dev/null @@ -1,185 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "treeRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "module", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "CURVE_ID", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MODULE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "TREE_ROOT", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "consume", - "inputs": [ - { - "name": "member", - "type": "address", - "internalType": "address" - }, - { - "name": "proof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hashLeaf", - "inputs": [ - { - "name": "member", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "pure" - }, - { - "type": "function", - "name": "isConsumed", - "inputs": [ - { - "name": "member", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "verifyProof", - "inputs": [ - { - "name": "member", - "type": "address", - "internalType": "address" - }, - { - "name": "proof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "event", - "name": "Consumed", - "inputs": [ - { - "name": "member", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AlreadyConsumed", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidCurveId", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidProof", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidTreeRoot", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotModule", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroModuleAddress", - "inputs": [] - } -] diff --git a/abi/CSFeeDistributor.json b/abi/CSFeeDistributor.json deleted file mode 100644 index 1b7572290..000000000 --- a/abi/CSFeeDistributor.json +++ /dev/null @@ -1,885 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "stETH", - "type": "address", - "internalType": "address" - }, - { - "name": "accounting", - "type": "address", - "internalType": "address" - }, - { - "name": "oracle", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "ACCOUNTING", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "ORACLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RECOVERER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "STETH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract IStETH" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "distributeFees", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "shares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "proof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [ - { - "name": "sharesToDistribute", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "distributedShares", - "inputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getFeesToDistribute", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "shares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "proof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [ - { - "name": "sharesToDistribute", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMember", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMemberCount", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "hashLeaf", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "shares", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "pure" - }, - { - "type": "function", - "name": "initialize", - "inputs": [ - { - "name": "admin", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "logCid", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "string", - "internalType": "string" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "pendingSharesToDistribute", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "processOracleReport", - "inputs": [ - { - "name": "_treeRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "_treeCid", - "type": "string", - "internalType": "string" - }, - { - "name": "_logCid", - "type": "string", - "internalType": "string" - }, - { - "name": "distributed", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC1155", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC20", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC721", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverEther", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "totalClaimableShares", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "treeCid", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "string", - "internalType": "string" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "treeRoot", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "event", - "name": "DistributionDataUpdated", - "inputs": [ - { - "name": "totalClaimableShares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "treeRoot", - "type": "bytes32", - "indexed": false, - "internalType": "bytes32" - }, - { - "name": "treeCid", - "type": "string", - "indexed": false, - "internalType": "string" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "DistributionLogUpdated", - "inputs": [ - { - "name": "logCid", - "type": "string", - "indexed": false, - "internalType": "string" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC1155Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC20Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC721Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "EtherRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "FeeDistributed", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Initialized", - "inputs": [ - { - "name": "version", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StETHSharesRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "FailedToSendEther", - "inputs": [] - }, - { - "type": "error", - "name": "FeeSharesDecrease", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialization", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidLogCID", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidProof", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidShares", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidTreeCID", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidTreeRoot", - "inputs": [] - }, - { - "type": "error", - "name": "NotAccounting", - "inputs": [] - }, - { - "type": "error", - "name": "NotAllowedToRecover", - "inputs": [] - }, - { - "type": "error", - "name": "NotEnoughShares", - "inputs": [] - }, - { - "type": "error", - "name": "NotInitializing", - "inputs": [] - }, - { - "type": "error", - "name": "NotOracle", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAccountingAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAdminAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroOracleAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroStEthAddress", - "inputs": [] - } -] diff --git a/abi/CSFeeOracle.json b/abi/CSFeeOracle.json deleted file mode 100644 index 26c11c25c..000000000 --- a/abi/CSFeeOracle.json +++ /dev/null @@ -1,1381 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "secondsPerSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "genesisTime", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "CONTRACT_MANAGER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "GENESIS_TIME", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MANAGE_CONSENSUS_CONTRACT_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MANAGE_CONSENSUS_VERSION_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_INFINITELY", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RECOVERER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RESUME_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "SECONDS_PER_SLOT", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "SUBMIT_DATA_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "avgPerfLeewayBP", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "discardConsensusReport", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "feeDistributor", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSFeeDistributor" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getConsensusContract", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getConsensusReport", - "inputs": [], - "outputs": [ - { - "name": "hash", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "refSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "processingDeadlineTime", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "processingStarted", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getConsensusVersion", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getContractVersion", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getLastProcessingRefSlot", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getResumeSinceTimestamp", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMember", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMemberCount", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "initialize", - "inputs": [ - { - "name": "admin", - "type": "address", - "internalType": "address" - }, - { - "name": "feeDistributorContract", - "type": "address", - "internalType": "address" - }, - { - "name": "consensusContract", - "type": "address", - "internalType": "address" - }, - { - "name": "consensusVersion", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "_avgPerfLeewayBP", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "isPaused", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "pauseFor", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "pauseUntil", - "inputs": [ - { - "name": "pauseUntilInclusive", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC1155", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC20", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC721", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverEther", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resume", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setConsensusContract", - "inputs": [ - { - "name": "addr", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setConsensusVersion", - "inputs": [ - { - "name": "version", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setFeeDistributorContract", - "inputs": [ - { - "name": "feeDistributorContract", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setPerformanceLeeway", - "inputs": [ - { - "name": "valueBP", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "submitConsensusReport", - "inputs": [ - { - "name": "reportHash", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "refSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "submitReportData", - "inputs": [ - { - "name": "data", - "type": "tuple", - "internalType": "struct CSFeeOracle.ReportData", - "components": [ - { - "name": "consensusVersion", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "refSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "treeRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "treeCid", - "type": "string", - "internalType": "string" - }, - { - "name": "logCid", - "type": "string", - "internalType": "string" - }, - { - "name": "distributed", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "name": "contractVersion", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "event", - "name": "ConsensusHashContractSet", - "inputs": [ - { - "name": "addr", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "prevAddr", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ConsensusVersionSet", - "inputs": [ - { - "name": "version", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "prevVersion", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ContractVersionSet", - "inputs": [ - { - "name": "version", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC1155Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC20Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC721Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "EtherRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "FeeDistributorContractSet", - "inputs": [ - { - "name": "feeDistributorContract", - "type": "address", - "indexed": false, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Initialized", - "inputs": [ - { - "name": "version", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Paused", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "PerfLeewaySet", - "inputs": [ - { - "name": "valueBP", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ProcessingStarted", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "hash", - "type": "bytes32", - "indexed": false, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ReportDiscarded", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "hash", - "type": "bytes32", - "indexed": false, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ReportSubmitted", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "hash", - "type": "bytes32", - "indexed": false, - "internalType": "bytes32" - }, - { - "name": "processingDeadlineTime", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Resumed", - "inputs": [], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StETHSharesRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "WarnProcessingMissed", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "AddressCannotBeSame", - "inputs": [] - }, - { - "type": "error", - "name": "AddressCannotBeZero", - "inputs": [] - }, - { - "type": "error", - "name": "FailedToSendEther", - "inputs": [] - }, - { - "type": "error", - "name": "HashCannotBeZero", - "inputs": [] - }, - { - "type": "error", - "name": "InitialRefSlotCannotBeLessThanProcessingOne", - "inputs": [ - { - "name": "initialRefSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "processingRefSlot", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "InvalidContractVersion", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidContractVersionIncrement", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialization", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidPerfLeeway", - "inputs": [] - }, - { - "type": "error", - "name": "NoConsensusReportToProcess", - "inputs": [] - }, - { - "type": "error", - "name": "NonZeroContractVersionOnInit", - "inputs": [] - }, - { - "type": "error", - "name": "NotAllowedToRecover", - "inputs": [] - }, - { - "type": "error", - "name": "NotInitializing", - "inputs": [] - }, - { - "type": "error", - "name": "PauseUntilMustBeInFuture", - "inputs": [] - }, - { - "type": "error", - "name": "PausedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "ProcessingDeadlineMissed", - "inputs": [ - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "RefSlotAlreadyProcessing", - "inputs": [] - }, - { - "type": "error", - "name": "RefSlotCannotDecrease", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "prevRefSlot", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "RefSlotMustBeGreaterThanProcessingOne", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "processingRefSlot", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "ResumedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "SafeCastOverflowedUintDowncast", - "inputs": [ - { - "name": "bits", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "SecondsPerSlotCannotBeZero", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotTheConsensusContract", - "inputs": [] - }, - { - "type": "error", - "name": "SenderNotAllowed", - "inputs": [] - }, - { - "type": "error", - "name": "UnexpectedChainConfig", - "inputs": [] - }, - { - "type": "error", - "name": "UnexpectedConsensusVersion", - "inputs": [ - { - "name": "expectedVersion", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "receivedVersion", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "UnexpectedContractVersion", - "inputs": [ - { - "name": "expected", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "received", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "UnexpectedDataHash", - "inputs": [ - { - "name": "consensusHash", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "receivedHash", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "UnexpectedRefSlot", - "inputs": [ - { - "name": "consensusRefSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "dataRefSlot", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "VersionCannotBeSame", - "inputs": [] - }, - { - "type": "error", - "name": "VersionCannotBeZero", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAdminAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroFeeDistributorAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroPauseDuration", - "inputs": [] - } -] diff --git a/abi/CSModule.json b/abi/CSModule.json deleted file mode 100644 index 58868ea49..000000000 --- a/abi/CSModule.json +++ /dev/null @@ -1,3033 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "moduleType", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "minSlashingPenaltyQuotient", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "elRewardsStealingFine", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "maxKeysPerOperatorEA", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "maxKeyRemovalCharge", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "lidoLocator", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "EL_REWARDS_STEALING_FINE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "INITIAL_SLASHING_PENALTY", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "LIDO_LOCATOR", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ILidoLocator" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MAX_KEY_REMOVAL_CHARGE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MAX_SIGNING_KEYS_PER_OPERATOR_BEFORE_PUBLIC_RELEASE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MODULE_MANAGER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_INFINITELY", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RECOVERER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RESUME_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "STAKING_ROUTER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "STETH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract IStETH" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "VERIFIER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "accounting", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSAccounting" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "activatePublicRelease", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "addNodeOperatorETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "managementProperties", - "type": "tuple", - "internalType": "struct NodeOperatorManagementProperties", - "components": [ - { - "name": "managerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "extendedManagerPermissions", - "type": "bool", - "internalType": "bool" - } - ] - }, - { - "name": "eaProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - }, - { - "name": "referrer", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "addNodeOperatorStETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "managementProperties", - "type": "tuple", - "internalType": "struct NodeOperatorManagementProperties", - "components": [ - { - "name": "managerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "extendedManagerPermissions", - "type": "bool", - "internalType": "bool" - } - ] - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "name": "eaProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - }, - { - "name": "referrer", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "addNodeOperatorWstETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "managementProperties", - "type": "tuple", - "internalType": "struct NodeOperatorManagementProperties", - "components": [ - { - "name": "managerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "extendedManagerPermissions", - "type": "bool", - "internalType": "bool" - } - ] - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "name": "eaProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - }, - { - "name": "referrer", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "addValidatorKeysETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "addValidatorKeysStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "addValidatorKeysWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "cancelELRewardsStealingPenalty", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "changeNodeOperatorRewardAddress", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "newAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsUnstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stEthAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "wstETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "cleanDepositQueue", - "inputs": [ - { - "name": "maxItems", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "removed", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "lastRemovedAtDepth", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "compensateELRewardsStealingPenalty", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "confirmNodeOperatorManagerAddressChange", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "confirmNodeOperatorRewardAddressChange", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "decreaseVettedSigningKeysCount", - "inputs": [ - { - "name": "nodeOperatorIds", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "vettedSigningKeysCounts", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "depositETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "depositQueue", - "inputs": [], - "outputs": [ - { - "name": "head", - "type": "uint128", - "internalType": "uint128" - }, - { - "name": "tail", - "type": "uint128", - "internalType": "uint128" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "depositQueueItem", - "inputs": [ - { - "name": "index", - "type": "uint128", - "internalType": "uint128" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "Batch" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "depositStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "depositWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "wstETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "earlyAdoption", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSEarlyAdoption" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getActiveNodeOperatorsCount", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperator", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct NodeOperator", - "components": [ - { - "name": "totalAddedKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "totalWithdrawnKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "totalDepositedKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "totalVettedKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "stuckValidatorsCount", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "depositableValidatorsCount", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "targetLimit", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "targetLimitMode", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "totalExitedKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "enqueuedCount", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "managerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "proposedManagerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "proposedRewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "extendedManagerPermissions", - "type": "bool", - "internalType": "bool" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorIds", - "inputs": [ - { - "name": "offset", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "limit", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "nodeOperatorIds", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorIsActive", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorNonWithdrawnKeys", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorSummary", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "targetLimitMode", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "targetValidatorsCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stuckValidatorsCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "refundedValidatorsCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stuckPenaltyEndTimestamp", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "totalExitedValidators", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "totalDepositedValidators", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "depositableValidatorsCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorsCount", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNonce", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getResumeSinceTimestamp", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMember", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMemberCount", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getSigningKeys", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "startIndex", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes", - "internalType": "bytes" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getSigningKeysWithSignatures", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "startIndex", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "keys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getStakingModuleSummary", - "inputs": [], - "outputs": [ - { - "name": "totalExitedValidators", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "totalDepositedValidators", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "depositableValidatorsCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getType", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "initialize", - "inputs": [ - { - "name": "_accounting", - "type": "address", - "internalType": "address" - }, - { - "name": "_earlyAdoption", - "type": "address", - "internalType": "address" - }, - { - "name": "_keyRemovalCharge", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "admin", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "isPaused", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "isValidatorSlashed", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "isValidatorWithdrawn", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "keyRemovalCharge", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "normalizeQueue", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "obtainDepositData", - "inputs": [ - { - "name": "depositsCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [ - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "onExitedAndStuckValidatorsCountsUpdated", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "onRewardsMinted", - "inputs": [ - { - "name": "totalShares", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "onWithdrawalCredentialsChanged", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "pauseFor", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "proposeNodeOperatorManagerAddressChange", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "proposedAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "proposeNodeOperatorRewardAddressChange", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "proposedAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "publicRelease", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "recoverERC1155", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC20", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC721", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverEther", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "removeKeys", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "startIndex", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "reportELRewardsStealingPenalty", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "blockHash", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resetNodeOperatorManagerAddress", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resume", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setKeyRemovalCharge", - "inputs": [ - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "settleELRewardsStealingPenalty", - "inputs": [ - { - "name": "nodeOperatorIds", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "submitInitialSlashing", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "submitWithdrawal", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "isSlashed", - "type": "bool", - "internalType": "bool" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "unsafeUpdateValidatorsCount", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "exitedValidatorsKeysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stuckValidatorsKeysCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateExitedValidatorsCount", - "inputs": [ - { - "name": "nodeOperatorIds", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "exitedValidatorsCounts", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateRefundedValidatorsCount", - "inputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateStuckValidatorsCount", - "inputs": [ - { - "name": "nodeOperatorIds", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "stuckValidatorsCounts", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateTargetValidatorsLimits", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "targetLimitMode", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "targetLimit", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "event", - "name": "BatchEnqueued", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "count", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "DepositableSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "depositableKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "DepositedSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "depositedKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ELRewardsStealingPenaltyCancelled", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ELRewardsStealingPenaltyCompensated", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ELRewardsStealingPenaltyReported", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "proposedBlockHash", - "type": "bytes32", - "indexed": false, - "internalType": "bytes32" - }, - { - "name": "stolenAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ELRewardsStealingPenaltySettled", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC1155Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC20Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC721Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "EtherRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ExitedSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "exitedKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "InitialSlashingSubmitted", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "pubkey", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Initialized", - "inputs": [ - { - "name": "version", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "KeyRemovalChargeApplied", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "KeyRemovalChargeSet", - "inputs": [ - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorAdded", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "managerAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorManagerAddressChangeProposed", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "oldProposedAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newProposedAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorManagerAddressChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "oldAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorRewardAddressChangeProposed", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "oldProposedAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newProposedAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorRewardAddressChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "oldAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NonceChanged", - "inputs": [ - { - "name": "nonce", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Paused", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "PublicRelease", - "inputs": [], - "anonymous": false - }, - { - "type": "event", - "name": "ReferrerSet", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "referrer", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Resumed", - "inputs": [], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "SigningKeyAdded", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "pubkey", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "SigningKeyRemoved", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "pubkey", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StETHSharesRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StuckSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "stuckKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "TargetValidatorsCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "targetLimitMode", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "targetValidatorsCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "TotalSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "totalKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "VettedSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "vettedKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "VettedSigningKeysCountDecreased", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "WithdrawalSubmitted", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "pubkey", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "AlreadyActivated", - "inputs": [] - }, - { - "type": "error", - "name": "AlreadyProposed", - "inputs": [] - }, - { - "type": "error", - "name": "AlreadySubmitted", - "inputs": [] - }, - { - "type": "error", - "name": "EmptyKey", - "inputs": [] - }, - { - "type": "error", - "name": "ExitedKeysDecrease", - "inputs": [] - }, - { - "type": "error", - "name": "ExitedKeysHigherThanTotalDeposited", - "inputs": [] - }, - { - "type": "error", - "name": "FailedToSendEther", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidAmount", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialization", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInput", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidKeysCount", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidLength", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidReportData", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidVetKeysPointer", - "inputs": [] - }, - { - "type": "error", - "name": "MaxSigningKeysCountExceeded", - "inputs": [] - }, - { - "type": "error", - "name": "MethodCallIsNotAllowed", - "inputs": [] - }, - { - "type": "error", - "name": "NodeOperatorDoesNotExist", - "inputs": [] - }, - { - "type": "error", - "name": "NotAllowedToJoinYet", - "inputs": [] - }, - { - "type": "error", - "name": "NotAllowedToRecover", - "inputs": [] - }, - { - "type": "error", - "name": "NotEnoughKeys", - "inputs": [] - }, - { - "type": "error", - "name": "NotInitializing", - "inputs": [] - }, - { - "type": "error", - "name": "NotSupported", - "inputs": [] - }, - { - "type": "error", - "name": "PauseUntilMustBeInFuture", - "inputs": [] - }, - { - "type": "error", - "name": "PausedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "QueueIsEmpty", - "inputs": [] - }, - { - "type": "error", - "name": "QueueLookupNoLimit", - "inputs": [] - }, - { - "type": "error", - "name": "ResumedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "SameAddress", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotEligible", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotManagerAddress", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotProposedAddress", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotRewardAddress", - "inputs": [] - }, - { - "type": "error", - "name": "SigningKeysInvalidOffset", - "inputs": [] - }, - { - "type": "error", - "name": "StuckKeysHigherThanNonExited", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAccountingAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAdminAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroLocatorAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroPauseDuration", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroRewardAddress", - "inputs": [] - } -] diff --git a/abi/CSModuleOld.json b/abi/CSModuleOld.json deleted file mode 100644 index b4b91bc2d..000000000 --- a/abi/CSModuleOld.json +++ /dev/null @@ -1,47 +0,0 @@ -[ - { - "type": "event", - "name": "InitialSlashingSubmitted", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - - { - "type": "event", - "name": "WithdrawalSubmitted", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - } -] diff --git a/abi/CSVerifier.json b/abi/CSVerifier.json deleted file mode 100644 index 47b479276..000000000 --- a/abi/CSVerifier.json +++ /dev/null @@ -1,711 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "withdrawalAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "module", - "type": "address", - "internalType": "address" - }, - { - "name": "slotsPerEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "gIFirstWithdrawalPrev", - "type": "bytes32", - "internalType": "GIndex" - }, - { - "name": "gIFirstWithdrawalCurr", - "type": "bytes32", - "internalType": "GIndex" - }, - { - "name": "gIFirstValidatorPrev", - "type": "bytes32", - "internalType": "GIndex" - }, - { - "name": "gIFirstValidatorCurr", - "type": "bytes32", - "internalType": "GIndex" - }, - { - "name": "gIHistoricalSummariesPrev", - "type": "bytes32", - "internalType": "GIndex" - }, - { - "name": "gIHistoricalSummariesCurr", - "type": "bytes32", - "internalType": "GIndex" - }, - { - "name": "firstSupportedSlot", - "type": "uint64", - "internalType": "Slot" - }, - { - "name": "pivotSlot", - "type": "uint64", - "internalType": "Slot" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "BEACON_ROOTS", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "FIRST_SUPPORTED_SLOT", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint64", - "internalType": "Slot" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "GI_FIRST_VALIDATOR_CURR", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "GIndex" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "GI_FIRST_VALIDATOR_PREV", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "GIndex" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "GI_FIRST_WITHDRAWAL_CURR", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "GIndex" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "GI_FIRST_WITHDRAWAL_PREV", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "GIndex" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "GI_HISTORICAL_SUMMARIES_CURR", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "GIndex" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "GI_HISTORICAL_SUMMARIES_PREV", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "GIndex" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MODULE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSModule" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PIVOT_SLOT", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint64", - "internalType": "Slot" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "SLOTS_PER_EPOCH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint64", - "internalType": "uint64" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "WITHDRAWAL_ADDRESS", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "processHistoricalWithdrawalProof", - "inputs": [ - { - "name": "beaconBlock", - "type": "tuple", - "internalType": "struct ICSVerifier.ProvableBeaconBlockHeader", - "components": [ - { - "name": "header", - "type": "tuple", - "internalType": "struct BeaconBlockHeader", - "components": [ - { - "name": "slot", - "type": "uint64", - "internalType": "Slot" - }, - { - "name": "proposerIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "parentRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "stateRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "bodyRoot", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "name": "rootsTimestamp", - "type": "uint64", - "internalType": "uint64" - } - ] - }, - { - "name": "oldBlock", - "type": "tuple", - "internalType": "struct ICSVerifier.HistoricalHeaderWitness", - "components": [ - { - "name": "header", - "type": "tuple", - "internalType": "struct BeaconBlockHeader", - "components": [ - { - "name": "slot", - "type": "uint64", - "internalType": "Slot" - }, - { - "name": "proposerIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "parentRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "stateRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "bodyRoot", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "name": "rootGIndex", - "type": "bytes32", - "internalType": "GIndex" - }, - { - "name": "proof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ] - }, - { - "name": "witness", - "type": "tuple", - "internalType": "struct ICSVerifier.WithdrawalWitness", - "components": [ - { - "name": "withdrawalOffset", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "withdrawalIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "validatorIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "amount", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "withdrawalCredentials", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "effectiveBalance", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "slashed", - "type": "bool", - "internalType": "bool" - }, - { - "name": "activationEligibilityEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "activationEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "exitEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "withdrawableEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "withdrawalProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - }, - { - "name": "validatorProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ] - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "processSlashingProof", - "inputs": [ - { - "name": "beaconBlock", - "type": "tuple", - "internalType": "struct ICSVerifier.ProvableBeaconBlockHeader", - "components": [ - { - "name": "header", - "type": "tuple", - "internalType": "struct BeaconBlockHeader", - "components": [ - { - "name": "slot", - "type": "uint64", - "internalType": "Slot" - }, - { - "name": "proposerIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "parentRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "stateRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "bodyRoot", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "name": "rootsTimestamp", - "type": "uint64", - "internalType": "uint64" - } - ] - }, - { - "name": "witness", - "type": "tuple", - "internalType": "struct ICSVerifier.SlashingWitness", - "components": [ - { - "name": "validatorIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "withdrawalCredentials", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "effectiveBalance", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "activationEligibilityEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "activationEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "exitEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "withdrawableEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "validatorProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ] - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "processWithdrawalProof", - "inputs": [ - { - "name": "beaconBlock", - "type": "tuple", - "internalType": "struct ICSVerifier.ProvableBeaconBlockHeader", - "components": [ - { - "name": "header", - "type": "tuple", - "internalType": "struct BeaconBlockHeader", - "components": [ - { - "name": "slot", - "type": "uint64", - "internalType": "Slot" - }, - { - "name": "proposerIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "parentRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "stateRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "bodyRoot", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "name": "rootsTimestamp", - "type": "uint64", - "internalType": "uint64" - } - ] - }, - { - "name": "witness", - "type": "tuple", - "internalType": "struct ICSVerifier.WithdrawalWitness", - "components": [ - { - "name": "withdrawalOffset", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "withdrawalIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "validatorIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "amount", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "withdrawalCredentials", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "effectiveBalance", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "slashed", - "type": "bool", - "internalType": "bool" - }, - { - "name": "activationEligibilityEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "activationEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "exitEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "withdrawableEpoch", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "withdrawalProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - }, - { - "name": "validatorProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ] - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "error", - "name": "IndexOutOfRange", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBlockHeader", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidChainConfig", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidGIndex", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidPivotSlot", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidWithdrawalAddress", - "inputs": [] - }, - { - "type": "error", - "name": "PartialWithdrawal", - "inputs": [] - }, - { - "type": "error", - "name": "RootNotFound", - "inputs": [] - }, - { - "type": "error", - "name": "UnsupportedSlot", - "inputs": [ - { - "name": "slot", - "type": "uint64", - "internalType": "Slot" - } - ] - }, - { - "type": "error", - "name": "ValidatorNotWithdrawn", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroModuleAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroWithdrawalAddress", - "inputs": [] - } -] diff --git a/abi/ExitBusOracle.json b/abi/ExitBusOracle.json deleted file mode 100644 index 424ed10be..000000000 --- a/abi/ExitBusOracle.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - { - "type": "event", - "name": "ValidatorExitRequest", - "inputs": [ - { - "name": "stakingModuleId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "validatorIndex", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "validatorPubkey", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - }, - { - "name": "timestamp", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - } -] diff --git a/abi/StakingRouter.json b/abi/StakingRouter.json deleted file mode 100644 index f2ad4b997..000000000 --- a/abi/StakingRouter.json +++ /dev/null @@ -1,2012 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_depositContract", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { "inputs": [], "name": "AppAuthLidoFailed", "type": "error" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "firstArrayLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "secondArrayLength", - "type": "uint256" - } - ], - "name": "ArraysLengthMismatch", - "type": "error" - }, - { "inputs": [], "name": "DepositContractZeroAddress", "type": "error" }, - { "inputs": [], "name": "DirectETHTransfer", "type": "error" }, - { "inputs": [], "name": "EmptyWithdrawalsCredentials", "type": "error" }, - { - "inputs": [], - "name": "ExitedValidatorsCountCannotDecrease", - "type": "error" - }, - { "inputs": [], "name": "InvalidContractVersionIncrement", "type": "error" }, - { - "inputs": [ - { "internalType": "uint256", "name": "etherValue", "type": "uint256" }, - { "internalType": "uint256", "name": "depositsCount", "type": "uint256" } - ], - "name": "InvalidDepositsValue", - "type": "error" - }, - { "inputs": [], "name": "InvalidFeeSum", "type": "error" }, - { "inputs": [], "name": "InvalidMaxDepositPerBlockValue", "type": "error" }, - { "inputs": [], "name": "InvalidMinDepositBlockDistance", "type": "error" }, - { - "inputs": [], - "name": "InvalidPriorityExitShareThreshold", - "type": "error" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "actual", "type": "uint256" }, - { "internalType": "uint256", "name": "expected", "type": "uint256" } - ], - "name": "InvalidPublicKeysBatchLength", - "type": "error" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "code", "type": "uint256" } - ], - "name": "InvalidReportData", - "type": "error" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "actual", "type": "uint256" }, - { "internalType": "uint256", "name": "expected", "type": "uint256" } - ], - "name": "InvalidSignaturesBatchLength", - "type": "error" - }, - { "inputs": [], "name": "InvalidStakeShareLimit", "type": "error" }, - { "inputs": [], "name": "NonZeroContractVersionOnInit", "type": "error" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "reportedExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositedValidatorsCount", - "type": "uint256" - } - ], - "name": "ReportedExitedValidatorsExceedDeposited", - "type": "error" - }, - { "inputs": [], "name": "StakingModuleAddressExists", "type": "error" }, - { "inputs": [], "name": "StakingModuleNotActive", "type": "error" }, - { "inputs": [], "name": "StakingModuleStatusTheSame", "type": "error" }, - { "inputs": [], "name": "StakingModuleUnregistered", "type": "error" }, - { "inputs": [], "name": "StakingModuleWrongName", "type": "error" }, - { "inputs": [], "name": "StakingModulesLimitExceeded", "type": "error" }, - { - "inputs": [ - { "internalType": "uint256", "name": "expected", "type": "uint256" }, - { "internalType": "uint256", "name": "received", "type": "uint256" } - ], - "name": "UnexpectedContractVersion", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentModuleExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "currentNodeOpExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "currentNodeOpStuckValidatorsCount", - "type": "uint256" - } - ], - "name": "UnexpectedCurrentValidatorsCount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newModuleTotalExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newModuleTotalExitedValidatorsCountInStakingRouter", - "type": "uint256" - } - ], - "name": "UnexpectedFinalExitedValidatorsCount", - "type": "error" - }, - { "inputs": [], "name": "UnrecoverableModuleError", "type": "error" }, - { "inputs": [], "name": "ZeroAddressAdmin", "type": "error" }, - { "inputs": [], "name": "ZeroAddressLido", "type": "error" }, - { "inputs": [], "name": "ZeroAddressStakingModule", "type": "error" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "version", - "type": "uint256" - } - ], - "name": "ContractVersionSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelRevertData", - "type": "bytes" - } - ], - "name": "ExitedAndStuckValidatorsCountsUpdateFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelRevertData", - "type": "bytes" - } - ], - "name": "RewardsMintedReportFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "stakingModule", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "address", - "name": "createdBy", - "type": "address" - } - ], - "name": "StakingModuleAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "unreportedExitedValidatorsCount", - "type": "uint256" - } - ], - "name": "StakingModuleExitedValidatorsIncompleteReporting", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "stakingModuleFee", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "treasuryFee", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleFeesSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maxDepositsPerBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleMaxDepositsPerBlockSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "minDepositBlockDistance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleMinDepositBlockDistanceSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "stakeShareLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "priorityExitShareThreshold", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleShareLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "enum StakingRouter.StakingModuleStatus", - "name": "status", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleStatusSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "StakingRouterETHDeposited", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "withdrawalCredentials", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "WithdrawalCredentialsSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelRevertData", - "type": "bytes" - } - ], - "name": "WithdrawalsCredentialsChangeFailed", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEPOSIT_CONTRACT", - "outputs": [ - { - "internalType": "contract IDepositContract", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "FEE_PRECISION_POINTS", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MANAGE_WITHDRAWAL_CREDENTIALS_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_STAKING_MODULES_COUNT", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_STAKING_MODULE_NAME_LENGTH", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REPORT_EXITED_VALIDATORS_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REPORT_REWARDS_MINTED_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "STAKING_MODULE_MANAGE_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "STAKING_MODULE_UNVETTING_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "TOTAL_BASIS_POINTS", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UNSAFE_SET_EXITED_VALIDATORS_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "string", "name": "_name", "type": "string" }, - { - "internalType": "address", - "name": "_stakingModuleAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_stakeShareLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_priorityExitShareThreshold", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_stakingModuleFee", - "type": "uint256" - }, - { "internalType": "uint256", "name": "_treasuryFee", "type": "uint256" }, - { - "internalType": "uint256", - "name": "_maxDepositsPerBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_minDepositBlockDistance", - "type": "uint256" - } - ], - "name": "addStakingModule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { "internalType": "bytes", "name": "_nodeOperatorIds", "type": "bytes" }, - { - "internalType": "bytes", - "name": "_vettedSigningKeysCounts", - "type": "bytes" - } - ], - "name": "decreaseStakingModuleVettedKeysCountByNodeOperator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_depositsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { "internalType": "bytes", "name": "_depositCalldata", "type": "bytes" } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "_priorityExitShareThresholds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_maxDepositsPerBlock", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_minDepositBlockDistances", - "type": "uint256[]" - } - ], - "name": "finalizeUpgrade_v2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getAllNodeOperatorDigests", - "outputs": [ - { - "components": [ - { "internalType": "uint256", "name": "id", "type": "uint256" }, - { "internalType": "bool", "name": "isActive", "type": "bool" }, - { - "components": [ - { - "internalType": "uint256", - "name": "targetLimitMode", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "targetValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stuckValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "refundedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stuckPenaltyEndTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.NodeOperatorSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.NodeOperatorDigest[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllStakingModuleDigests", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nodeOperatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "activeNodeOperatorsCount", - "type": "uint256" - }, - { - "components": [ - { "internalType": "uint24", "name": "id", "type": "uint24" }, - { - "internalType": "address", - "name": "stakingModuleAddress", - "type": "address" - }, - { - "internalType": "uint16", - "name": "stakingModuleFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "treasuryFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "stakeShareLimit", - "type": "uint16" - }, - { "internalType": "uint8", "name": "status", "type": "uint8" }, - { "internalType": "string", "name": "name", "type": "string" }, - { - "internalType": "uint64", - "name": "lastDepositAt", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "lastDepositBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "exitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "priorityExitShareThreshold", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxDepositsPerBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "minDepositBlockDistance", - "type": "uint64" - } - ], - "internalType": "struct StakingRouter.StakingModule", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.StakingModuleSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.StakingModuleDigest[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getContractVersion", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "_depositsCount", "type": "uint256" } - ], - "name": "getDepositsAllocation", - "outputs": [ - { "internalType": "uint256", "name": "allocated", "type": "uint256" }, - { - "internalType": "uint256[]", - "name": "allocations", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLido", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_nodeOperatorIds", - "type": "uint256[]" - } - ], - "name": "getNodeOperatorDigests", - "outputs": [ - { - "components": [ - { "internalType": "uint256", "name": "id", "type": "uint256" }, - { "internalType": "bool", "name": "isActive", "type": "bool" }, - { - "components": [ - { - "internalType": "uint256", - "name": "targetLimitMode", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "targetValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stuckValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "refundedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stuckPenaltyEndTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.NodeOperatorSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.NodeOperatorDigest[]", - "name": "digests", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { "internalType": "uint256", "name": "_offset", "type": "uint256" }, - { "internalType": "uint256", "name": "_limit", "type": "uint256" } - ], - "name": "getNodeOperatorDigests", - "outputs": [ - { - "components": [ - { "internalType": "uint256", "name": "id", "type": "uint256" }, - { "internalType": "bool", "name": "isActive", "type": "bool" }, - { - "components": [ - { - "internalType": "uint256", - "name": "targetLimitMode", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "targetValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stuckValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "refundedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stuckPenaltyEndTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.NodeOperatorSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.NodeOperatorDigest[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - } - ], - "name": "getNodeOperatorSummary", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "targetLimitMode", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "targetValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stuckValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "refundedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stuckPenaltyEndTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.NodeOperatorSummary", - "name": "summary", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" } - ], - "name": "getRoleAdmin", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "uint256", "name": "index", "type": "uint256" } - ], - "name": "getRoleMember", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" } - ], - "name": "getRoleMemberCount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingFeeAggregateDistribution", - "outputs": [ - { "internalType": "uint96", "name": "modulesFee", "type": "uint96" }, - { "internalType": "uint96", "name": "treasuryFee", "type": "uint96" }, - { "internalType": "uint256", "name": "basePrecision", "type": "uint256" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingFeeAggregateDistributionE4Precision", - "outputs": [ - { "internalType": "uint16", "name": "modulesFee", "type": "uint16" }, - { "internalType": "uint16", "name": "treasuryFee", "type": "uint16" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModule", - "outputs": [ - { - "components": [ - { "internalType": "uint24", "name": "id", "type": "uint24" }, - { - "internalType": "address", - "name": "stakingModuleAddress", - "type": "address" - }, - { - "internalType": "uint16", - "name": "stakingModuleFee", - "type": "uint16" - }, - { "internalType": "uint16", "name": "treasuryFee", "type": "uint16" }, - { - "internalType": "uint16", - "name": "stakeShareLimit", - "type": "uint16" - }, - { "internalType": "uint8", "name": "status", "type": "uint8" }, - { "internalType": "string", "name": "name", "type": "string" }, - { - "internalType": "uint64", - "name": "lastDepositAt", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "lastDepositBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "exitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "priorityExitShareThreshold", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxDepositsPerBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "minDepositBlockDistance", - "type": "uint64" - } - ], - "internalType": "struct StakingRouter.StakingModule", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleActiveValidatorsCount", - "outputs": [ - { - "internalType": "uint256", - "name": "activeValidatorsCount", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "_stakingModuleIds", - "type": "uint256[]" - } - ], - "name": "getStakingModuleDigests", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nodeOperatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "activeNodeOperatorsCount", - "type": "uint256" - }, - { - "components": [ - { "internalType": "uint24", "name": "id", "type": "uint24" }, - { - "internalType": "address", - "name": "stakingModuleAddress", - "type": "address" - }, - { - "internalType": "uint16", - "name": "stakingModuleFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "treasuryFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "stakeShareLimit", - "type": "uint16" - }, - { "internalType": "uint8", "name": "status", "type": "uint8" }, - { "internalType": "string", "name": "name", "type": "string" }, - { - "internalType": "uint64", - "name": "lastDepositAt", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "lastDepositBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "exitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "priorityExitShareThreshold", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxDepositsPerBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "minDepositBlockDistance", - "type": "uint64" - } - ], - "internalType": "struct StakingRouter.StakingModule", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.StakingModuleSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.StakingModuleDigest[]", - "name": "digests", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingModuleIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "stakingModuleIds", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleIsActive", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleIsDepositsPaused", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleIsStopped", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleLastDepositBlock", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxDepositsValue", - "type": "uint256" - } - ], - "name": "getStakingModuleMaxDepositsCount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleMaxDepositsPerBlock", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleMinDepositBlockDistance", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleNonce", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleStatus", - "outputs": [ - { - "internalType": "enum StakingRouter.StakingModuleStatus", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleSummary", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.StakingModuleSummary", - "name": "summary", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingModules", - "outputs": [ - { - "components": [ - { "internalType": "uint24", "name": "id", "type": "uint24" }, - { - "internalType": "address", - "name": "stakingModuleAddress", - "type": "address" - }, - { - "internalType": "uint16", - "name": "stakingModuleFee", - "type": "uint16" - }, - { "internalType": "uint16", "name": "treasuryFee", "type": "uint16" }, - { - "internalType": "uint16", - "name": "stakeShareLimit", - "type": "uint16" - }, - { "internalType": "uint8", "name": "status", "type": "uint8" }, - { "internalType": "string", "name": "name", "type": "string" }, - { - "internalType": "uint64", - "name": "lastDepositAt", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "lastDepositBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "exitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "priorityExitShareThreshold", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxDepositsPerBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "minDepositBlockDistance", - "type": "uint64" - } - ], - "internalType": "struct StakingRouter.StakingModule[]", - "name": "res", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingModulesCount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingRewardsDistribution", - "outputs": [ - { - "internalType": "address[]", - "name": "recipients", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "stakingModuleIds", - "type": "uint256[]" - }, - { - "internalType": "uint96[]", - "name": "stakingModuleFees", - "type": "uint96[]" - }, - { "internalType": "uint96", "name": "totalFee", "type": "uint96" }, - { - "internalType": "uint256", - "name": "precisionPoints", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalFeeE4Precision", - "outputs": [ - { "internalType": "uint16", "name": "totalFee", "type": "uint16" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWithdrawalCredentials", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "hasRole", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "hasStakingModule", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "_admin", "type": "address" }, - { "internalType": "address", "name": "_lido", "type": "address" }, - { - "internalType": "bytes32", - "name": "_withdrawalCredentials", - "type": "bytes32" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "onValidatorsCountsByNodeOperatorReportingFinished", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "_stakingModuleIds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_totalShares", - "type": "uint256[]" - } - ], - "name": "reportRewardsMinted", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { "internalType": "bytes", "name": "_nodeOperatorIds", "type": "bytes" }, - { - "internalType": "bytes", - "name": "_exitedValidatorsCounts", - "type": "bytes" - } - ], - "name": "reportStakingModuleExitedValidatorsCountByNodeOperator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { "internalType": "bytes", "name": "_nodeOperatorIds", "type": "bytes" }, - { - "internalType": "bytes", - "name": "_stuckValidatorsCounts", - "type": "bytes" - } - ], - "name": "reportStakingModuleStuckValidatorsCountByNodeOperator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "enum StakingRouter.StakingModuleStatus", - "name": "_status", - "type": "uint8" - } - ], - "name": "setStakingModuleStatus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_withdrawalCredentials", - "type": "bytes32" - } - ], - "name": "setWithdrawalCredentials", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } - ], - "name": "supportsInterface", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "_triggerUpdateFinish", - "type": "bool" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "currentModuleExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "currentNodeOperatorExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "currentNodeOperatorStuckValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newModuleExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newNodeOperatorExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newNodeOperatorStuckValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.ValidatorsCountsCorrection", - "name": "_correction", - "type": "tuple" - } - ], - "name": "unsafeSetExitedValidatorsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "_stakingModuleIds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_exitedValidatorsCounts", - "type": "uint256[]" - } - ], - "name": "updateExitedValidatorsCountByStakingModule", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_refundedValidatorsCount", - "type": "uint256" - } - ], - "name": "updateRefundedValidatorsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_stakeShareLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_priorityExitShareThreshold", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_stakingModuleFee", - "type": "uint256" - }, - { "internalType": "uint256", "name": "_treasuryFee", "type": "uint256" }, - { - "internalType": "uint256", - "name": "_maxDepositsPerBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_minDepositBlockDistance", - "type": "uint256" - } - ], - "name": "updateStakingModule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_targetLimitMode", - "type": "uint256" - }, - { "internalType": "uint256", "name": "_targetLimit", "type": "uint256" } - ], - "name": "updateTargetValidatorsLimits", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { "stateMutability": "payable", "type": "receive" } -] diff --git a/abi/aggregator-abi.ts b/abi/aggregator-abi.ts new file mode 100644 index 000000000..73b36489c --- /dev/null +++ b/abi/aggregator-abi.ts @@ -0,0 +1,201 @@ +export const AggregatorAbi = [ + { + inputs: [ + { internalType: 'address', name: '_aggregator', type: 'address' }, + { internalType: 'address', name: '_accessController', type: 'address' }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'int256', + name: 'current', + type: 'int256', + }, + { + indexed: true, + internalType: 'uint256', + name: 'roundId', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'updatedAt', + type: 'uint256', + }, + ], + name: 'AnswerUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'roundId', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'startedBy', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'startedAt', + type: 'uint256', + }, + ], + name: 'NewRound', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + ], + name: 'OwnershipTransferRequested', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + ], + name: 'OwnershipTransferred', + type: 'event', + }, + { + inputs: [], + name: 'acceptOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'accessController', + outputs: [ + { + internalType: 'contract AccessControllerInterface', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'aggregator', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_aggregator', type: 'address' }], + name: 'confirmAggregator', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'decimals', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'description', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_roundId', type: 'uint256' }], + name: 'getAnswer', + outputs: [{ internalType: 'int256', name: '', type: 'int256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint80', name: '_roundId', type: 'uint80' }], + name: 'getRoundData', + outputs: [ + { internalType: 'uint80', name: 'roundId', type: 'uint80' }, + { internalType: 'int256', name: 'answer', type: 'int256' }, + { internalType: 'uint256', name: 'startedAt', type: 'uint256' }, + { internalType: 'uint256', name: 'updatedAt', type: 'uint256' }, + { internalType: 'uint80', name: 'answeredInRound', type: 'uint80' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_roundId', type: 'uint256' }], + name: 'getTimestamp', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'latestAnswer', + outputs: [{ internalType: 'int256', name: '', type: 'int256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'latestRound', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'latestRoundData', + outputs: [ + { internalType: 'uint80', name: 'roundId', type: 'uint80' }, + { internalType: 'int256', name: 'answer', type: 'int256' }, + { internalType: 'uint256', name: 'startedAt', type: 'uint256' }, + { internalType: 'uint256', name: 'updatedAt', type: 'uint256' }, + { internalType: 'uint80', name: 'answeredInRound', type: 'uint80' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'owner', + outputs: [{ internalType: 'address payable', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_to', type: 'address' }], + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'version', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, +] as const; diff --git a/abi/ens-registry-abi.ts b/abi/ens-registry-abi.ts new file mode 100644 index 000000000..373733b89 --- /dev/null +++ b/abi/ens-registry-abi.ts @@ -0,0 +1,205 @@ +export const ENSRegistryAbi = [ + { + inputs: [{ internalType: 'contract ENS', name: '_old', type: 'address' }], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { indexed: false, internalType: 'bool', name: 'approved', type: 'bool' }, + ], + name: 'ApprovalForAll', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { + indexed: true, + internalType: 'bytes32', + name: 'label', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'address', + name: 'owner', + type: 'address', + }, + ], + name: 'NewOwner', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { + indexed: false, + internalType: 'address', + name: 'resolver', + type: 'address', + }, + ], + name: 'NewResolver', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { indexed: false, internalType: 'uint64', name: 'ttl', type: 'uint64' }, + ], + name: 'NewTTL', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { + indexed: false, + internalType: 'address', + name: 'owner', + type: 'address', + }, + ], + name: 'Transfer', + type: 'event', + }, + { + inputs: [ + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'operator', type: 'address' }, + ], + name: 'isApprovedForAll', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'old', + outputs: [{ internalType: 'contract ENS', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'node', type: 'bytes32' }], + name: 'owner', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'node', type: 'bytes32' }], + name: 'recordExists', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'node', type: 'bytes32' }], + name: 'resolver', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'operator', type: 'address' }, + { internalType: 'bool', name: 'approved', type: 'bool' }, + ], + name: 'setApprovalForAll', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { internalType: 'address', name: 'owner', type: 'address' }, + ], + name: 'setOwner', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'resolver', type: 'address' }, + { internalType: 'uint64', name: 'ttl', type: 'uint64' }, + ], + name: 'setRecord', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { internalType: 'address', name: 'resolver', type: 'address' }, + ], + name: 'setResolver', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { internalType: 'bytes32', name: 'label', type: 'bytes32' }, + { internalType: 'address', name: 'owner', type: 'address' }, + ], + name: 'setSubnodeOwner', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { internalType: 'bytes32', name: 'label', type: 'bytes32' }, + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'resolver', type: 'address' }, + { internalType: 'uint64', name: 'ttl', type: 'uint64' }, + ], + name: 'setSubnodeRecord', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { internalType: 'uint64', name: 'ttl', type: 'uint64' }, + ], + name: 'setTTL', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'node', type: 'bytes32' }], + name: 'ttl', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, +] as const; diff --git a/abi/ens-resolver-abi.ts b/abi/ens-resolver-abi.ts new file mode 100644 index 000000000..6139f31f6 --- /dev/null +++ b/abi/ens-resolver-abi.ts @@ -0,0 +1,190 @@ +export const ENSResolverAbi = [ + { + inputs: [{ internalType: 'contract ENS', name: '_ens', type: 'address' }], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { + indexed: true, + internalType: 'uint256', + name: 'contentType', + type: 'uint256', + }, + ], + name: 'ABIChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { indexed: false, internalType: 'address', name: 'a', type: 'address' }, + ], + name: 'AddrChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { + indexed: false, + internalType: 'uint256', + name: 'coinType', + type: 'uint256', + }, + { + indexed: false, + internalType: 'bytes', + name: 'newAddress', + type: 'bytes', + }, + ], + name: 'AddressChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'target', + type: 'address', + }, + { + indexed: false, + internalType: 'bool', + name: 'isAuthorised', + type: 'bool', + }, + ], + name: 'AuthorisationChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { indexed: false, internalType: 'bytes', name: 'hash', type: 'bytes' }, + ], + name: 'ContenthashChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { indexed: false, internalType: 'bytes', name: 'name', type: 'bytes' }, + { + indexed: false, + internalType: 'uint16', + name: 'resource', + type: 'uint16', + }, + { indexed: false, internalType: 'bytes', name: 'record', type: 'bytes' }, + ], + name: 'DNSRecordChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { indexed: false, internalType: 'bytes', name: 'name', type: 'bytes' }, + { + indexed: false, + internalType: 'uint16', + name: 'resource', + type: 'uint16', + }, + ], + name: 'DNSRecordDeleted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + ], + name: 'DNSZoneCleared', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { + indexed: true, + internalType: 'bytes4', + name: 'interfaceID', + type: 'bytes4', + }, + { + indexed: false, + internalType: 'address', + name: 'implementer', + type: 'address', + }, + ], + name: 'InterfaceChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { indexed: false, internalType: 'string', name: 'name', type: 'string' }, + ], + name: 'NameChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { indexed: false, internalType: 'bytes32', name: 'x', type: 'bytes32' }, + { indexed: false, internalType: 'bytes32', name: 'y', type: 'bytes32' }, + ], + name: 'PubkeyChanged', + type: 'event', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { internalType: 'string', name: 'key', type: 'string' }, + ], + name: 'text', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'node', type: 'bytes32' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'setDNSRecords', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes4', name: 'interfaceID', type: 'bytes4' }], + name: 'supportsInterface', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'pure', + type: 'function', + }, +] as const; diff --git a/abi/ens-universal-resolver-abi.ts b/abi/ens-universal-resolver-abi.ts new file mode 100644 index 000000000..a507fae97 --- /dev/null +++ b/abi/ens-universal-resolver-abi.ts @@ -0,0 +1,32 @@ +// ENS Universal Resolver ABI (resolve + reverse functions used by viem) +export const ENSUniversalResolverAbi = [ + { + name: 'resolveWithGateways', + type: 'function', + stateMutability: 'view', + inputs: [ + { name: 'name', type: 'bytes' }, + { name: 'data', type: 'bytes' }, + { name: 'gateways', type: 'string[]' }, + ], + outputs: [ + { name: '', type: 'bytes' }, + { name: 'address', type: 'address' }, + ], + }, + { + name: 'reverseWithGateways', + type: 'function', + stateMutability: 'view', + inputs: [ + { type: 'bytes', name: 'reverseName' }, + { type: 'uint256', name: 'coinType' }, + { type: 'string[]', name: 'gateways' }, + ], + outputs: [ + { type: 'string', name: 'resolvedName' }, + { type: 'address', name: 'resolver' }, + { type: 'address', name: 'reverseResolver' }, + ], + }, +] as const; diff --git a/assets/balance/bond.svg b/assets/balance/bond.svg new file mode 100644 index 000000000..8399a7571 --- /dev/null +++ b/assets/balance/bond.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/balance/empty.svg b/assets/balance/empty.svg new file mode 100644 index 000000000..7d8bdf7c2 --- /dev/null +++ b/assets/balance/empty.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/assets/balance/rewards.svg b/assets/balance/rewards.svg new file mode 100644 index 000000000..57def1642 --- /dev/null +++ b/assets/balance/rewards.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/assets/cm-light.png b/assets/cm-light.png new file mode 100644 index 000000000..7c650e8a4 Binary files /dev/null and b/assets/cm-light.png differ diff --git a/assets/csm-dark.png b/assets/csm-dark.png index 57b0c5bdf..aa2895da4 100644 Binary files a/assets/csm-dark.png and b/assets/csm-dark.png differ diff --git a/assets/csm-light.png b/assets/csm-light.png index 0b3b797cc..1d1138cc2 100644 Binary files a/assets/csm-light.png and b/assets/csm-light.png differ diff --git a/assets/icons/arrow-down.svg b/assets/icons/arrow-down.svg new file mode 100644 index 000000000..4727f6047 --- /dev/null +++ b/assets/icons/arrow-down.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/arrow-forward.svg b/assets/icons/arrow-forward.svg new file mode 100644 index 000000000..2fcca9190 --- /dev/null +++ b/assets/icons/arrow-forward.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/arrow-up.svg b/assets/icons/arrow-up.svg new file mode 100644 index 000000000..4d6d5b2be --- /dev/null +++ b/assets/icons/arrow-up.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/attention-triangle.svg b/assets/icons/attention-triangle.svg new file mode 100644 index 000000000..3d09ced4a --- /dev/null +++ b/assets/icons/attention-triangle.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/beaconcha-link.svg b/assets/icons/beaconcha-link.svg new file mode 100644 index 000000000..3912b60f6 --- /dev/null +++ b/assets/icons/beaconcha-link.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/icons/clock.svg b/assets/icons/clock.svg new file mode 100644 index 000000000..67422f046 --- /dev/null +++ b/assets/icons/clock.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/csm.svg b/assets/icons/csm.svg new file mode 100644 index 000000000..5746674d5 --- /dev/null +++ b/assets/icons/csm.svg @@ -0,0 +1,57 @@ + + +
+ + + + + +
+ + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/assets/icons/download.svg b/assets/icons/download.svg new file mode 100644 index 000000000..7d7180832 --- /dev/null +++ b/assets/icons/download.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/ethseer.svg b/assets/icons/ethseer.svg deleted file mode 100644 index d3c1ead2a..000000000 --- a/assets/icons/ethseer.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/assets/icons/gift.svg b/assets/icons/gift.svg new file mode 100644 index 000000000..18915bab6 --- /dev/null +++ b/assets/icons/gift.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/ics-scores/aragon.png b/assets/icons/ics-scores/aragon.png new file mode 100644 index 000000000..a2d16d2fa Binary files /dev/null and b/assets/icons/ics-scores/aragon.png differ diff --git a/assets/icons/ics-scores/circles.png b/assets/icons/ics-scores/circles.png new file mode 100644 index 000000000..977683cc3 Binary files /dev/null and b/assets/icons/ics-scores/circles.png differ diff --git a/assets/icons/ics-scores/csm.png b/assets/icons/ics-scores/csm.png new file mode 100644 index 000000000..8cb875379 Binary files /dev/null and b/assets/icons/ics-scores/csm.png differ diff --git a/assets/icons/ics-scores/discord.png b/assets/icons/ics-scores/discord.png new file mode 100644 index 000000000..c0550f3a9 Binary files /dev/null and b/assets/icons/ics-scores/discord.png differ diff --git a/assets/icons/ics-scores/ethstaker.png b/assets/icons/ics-scores/ethstaker.png new file mode 100644 index 000000000..ec9389d64 Binary files /dev/null and b/assets/icons/ics-scores/ethstaker.png differ diff --git a/assets/icons/ics-scores/galxe.png b/assets/icons/ics-scores/galxe.png new file mode 100644 index 000000000..57d368dad Binary files /dev/null and b/assets/icons/ics-scores/galxe.png differ diff --git a/assets/icons/ics-scores/git-poap.png b/assets/icons/ics-scores/git-poap.png new file mode 100644 index 000000000..439e149a7 Binary files /dev/null and b/assets/icons/ics-scores/git-poap.png differ diff --git a/assets/icons/ics-scores/high-signal.png b/assets/icons/ics-scores/high-signal.png new file mode 100644 index 000000000..d82b8a134 Binary files /dev/null and b/assets/icons/ics-scores/high-signal.png differ diff --git a/assets/icons/ics-scores/humal-passport.png b/assets/icons/ics-scores/humal-passport.png new file mode 100644 index 000000000..9f9d3afbd Binary files /dev/null and b/assets/icons/ics-scores/humal-passport.png differ diff --git a/assets/icons/ics-scores/obol.png b/assets/icons/ics-scores/obol.png new file mode 100644 index 000000000..330875ace Binary files /dev/null and b/assets/icons/ics-scores/obol.png differ diff --git a/assets/icons/ics-scores/sdvt.png b/assets/icons/ics-scores/sdvt.png new file mode 100644 index 000000000..8e7649b44 Binary files /dev/null and b/assets/icons/ics-scores/sdvt.png differ diff --git a/assets/icons/ics-scores/snapshot.png b/assets/icons/ics-scores/snapshot.png new file mode 100644 index 000000000..3a4a4c5c9 Binary files /dev/null and b/assets/icons/ics-scores/snapshot.png differ diff --git a/assets/icons/ics-scores/ssv.png b/assets/icons/ics-scores/ssv.png new file mode 100644 index 000000000..02a3db0d1 Binary files /dev/null and b/assets/icons/ics-scores/ssv.png differ diff --git a/assets/icons/ics-scores/stakecat.png b/assets/icons/ics-scores/stakecat.png new file mode 100644 index 000000000..be568d533 Binary files /dev/null and b/assets/icons/ics-scores/stakecat.png differ diff --git a/assets/icons/ics-scores/x.png b/assets/icons/ics-scores/x.png new file mode 100644 index 000000000..6d4e5700a Binary files /dev/null and b/assets/icons/ics-scores/x.png differ diff --git a/assets/icons/meter.svg b/assets/icons/meter.svg new file mode 100644 index 000000000..52f79c4c8 --- /dev/null +++ b/assets/icons/meter.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/migalabs-link.svg b/assets/icons/migalabs-link.svg new file mode 100644 index 000000000..87b6de943 --- /dev/null +++ b/assets/icons/migalabs-link.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/migalabs.svg b/assets/icons/migalabs.svg new file mode 100644 index 000000000..a85ac8b83 --- /dev/null +++ b/assets/icons/migalabs.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/radio.svg b/assets/icons/radio.svg index 75a0fba44..8f126c192 100644 --- a/assets/icons/radio.svg +++ b/assets/icons/radio.svg @@ -1,3 +1,4 @@ - + diff --git a/assets/icons/triangle-down.svg b/assets/icons/triangle-down.svg new file mode 100644 index 000000000..d4b5489c9 --- /dev/null +++ b/assets/icons/triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/triangle-up.svg b/assets/icons/triangle-up.svg new file mode 100644 index 000000000..408cd1475 --- /dev/null +++ b/assets/icons/triangle-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/user.svg b/assets/icons/user.svg new file mode 100644 index 000000000..218299c25 --- /dev/null +++ b/assets/icons/user.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/wrapped/outro.svg b/assets/wrapped/outro.svg new file mode 100644 index 000000000..5ff60babe --- /dev/null +++ b/assets/wrapped/outro.svg @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/wrapped/wrap.png b/assets/wrapped/wrap.png new file mode 100644 index 000000000..c533734f7 Binary files /dev/null and b/assets/wrapped/wrap.png differ diff --git a/commitlint.config.cjs b/commitlint.config.cjs deleted file mode 100644 index ca4b773a4..000000000 --- a/commitlint.config.cjs +++ /dev/null @@ -1,6 +0,0 @@ -// This file has .cjs extension and CJS exports because of this issue: -// https://github.com/conventional-changelog/commitlint/issues/3251 - -module.exports = { - extends: ['@commitlint/config-conventional'], -}; diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 000000000..08d480b85 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,6 @@ +// This file has .cjs extension and CJS exports because of this issue: +// https://github.com/conventional-changelog/commitlint/issues/3251 + +export default { + extends: ['@commitlint/config-conventional'], +}; diff --git a/config/csp/index.ts b/config/csp/index.ts index 888fdb4ed..84c956ebb 100644 --- a/config/csp/index.ts +++ b/config/csp/index.ts @@ -19,16 +19,12 @@ export const contentSecurityPolicy: ContentSecurityPolicyOption = { directives: { 'default-src': ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], - fontSrc: ["'self'", 'data:'], - imgSrc: [ - "'self'", - 'data:', - 'https://*.walletconnect.org', - 'https://*.walletconnect.com', - ], + fontSrc: ["'self'", 'data:', 'https://fonts.reown.com'], + imgSrc: ["'self'", 'data:', 'blob:'], scriptSrc: [ "'self'", "'unsafe-inline'", + "'wasm-unsafe-eval'", ...(config.developmentMode ? ["'unsafe-eval'"] : []), // for HMR ...trustedHosts, ], diff --git a/config/feature-flags/context-hook.tsx b/config/feature-flags/context-hook.tsx index 78eb24fc0..58bafad7b 100644 --- a/config/feature-flags/context-hook.tsx +++ b/config/feature-flags/context-hook.tsx @@ -1,8 +1,8 @@ -import { useMemo, useState, useCallback } from 'react'; -import { useLocalStorage } from '@lido-sdk/react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; -import { getFeatureFlagsDefault } from './utils'; +import { useLocalStorage } from 'shared/hooks/use-local-storage'; import { FeatureFlagsType } from './types'; +import { getFeatureFlagsDefault } from './utils'; const STORAGE_FEATURE_FLAGS = 'lido-feature-flags'; @@ -17,19 +17,21 @@ export const useFeatureFlagsContext = () => { useLocalStorage(STORAGE_FEATURE_FLAGS, FEATURE_FLAGS_DEFAULT); const [featureFlagsState, setFeatureFlagsState] = useState( - featureFlagsLocalStorage, + FEATURE_FLAGS_DEFAULT, ); + useEffect(() => { + setFeatureFlagsState(featureFlagsLocalStorage); + }, [featureFlagsLocalStorage]); + const setFeatureFlag = useCallback( (featureFlag: keyof FeatureFlagsType, value: boolean) => { - setFeatureFlagsLocalStorage({ - ...featureFlagsState, - [featureFlag]: value, - }); - setFeatureFlagsState({ + const newFlags = { ...featureFlagsState, [featureFlag]: value, - }); + }; + setFeatureFlagsLocalStorage(newFlags); + setFeatureFlagsState(newFlags); }, [featureFlagsState, setFeatureFlagsLocalStorage], ); diff --git a/config/feature-flags/hooks.ts b/config/feature-flags/hooks.ts index 3fcaa9553..8d18d3cf0 100644 --- a/config/feature-flags/hooks.ts +++ b/config/feature-flags/hooks.ts @@ -5,22 +5,22 @@ import { ConfigContext } from '../provider'; import { FeatureFlagsContextType } from './context-hook'; import { FeatureFlagsType } from './types'; -type UseFeatureFlagReturnType = { - [key in keyof FeatureFlagsType]: boolean; +type UseFeatureFlagReturnType = { + [key in T]: boolean; } & { setFeatureFlag: (featureFlag: keyof FeatureFlagsType, value: boolean) => void; }; -export const useFeatureFlag = ( - flag: keyof FeatureFlagsType, -): UseFeatureFlagReturnType | null => { +export const useFeatureFlag = ( + flag: T, +): UseFeatureFlagReturnType | null => { const context = useContext(ConfigContext); invariant(context, 'Attempt to use `feature flag` outside of provider'); return useMemo(() => { return { [flag]: context.featureFlags[flag], setFeatureFlag: context.featureFlags?.setFeatureFlag, - }; + } as UseFeatureFlagReturnType; }, [context.featureFlags, flag]); }; diff --git a/config/feature-flags/types.ts b/config/feature-flags/types.ts index ec8a110b3..428e04e3a 100644 --- a/config/feature-flags/types.ts +++ b/config/feature-flags/types.ts @@ -1,6 +1,9 @@ -export const RPC_SETTINGS_PAGE_ON_INFRA_IS_ENABLED = - 'rpcSettingsPageOnInfraIsEnabled'; +export const ICS_APPLY_FORM = 'icsApplyForm'; +export const SURVEYS_SETUP_ENABLED = 'surveysSetupEnabled'; +export const DISABLE_DEPOSIT_DATA_VALIDATION = 'disableDepositDataValidation'; export type FeatureFlagsType = { - [RPC_SETTINGS_PAGE_ON_INFRA_IS_ENABLED]: boolean; + [ICS_APPLY_FORM]: boolean; + [SURVEYS_SETUP_ENABLED]: boolean; + [DISABLE_DEPOSIT_DATA_VALIDATION]: boolean; }; diff --git a/config/feature-flags/utils.ts b/config/feature-flags/utils.ts index d4d721b5f..cea935c00 100644 --- a/config/feature-flags/utils.ts +++ b/config/feature-flags/utils.ts @@ -1,7 +1,19 @@ -import { FeatureFlagsType } from './types'; +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; +import { getConfig } from 'config/get-config'; +import { + FeatureFlagsType, + ICS_APPLY_FORM, + SURVEYS_SETUP_ENABLED, + DISABLE_DEPOSIT_DATA_VALIDATION, +} from './types'; + +const { defaultChain } = getConfig(); +const isMainnet = defaultChain === CHAINS.Mainnet; export const getFeatureFlagsDefault = (): FeatureFlagsType => { return { - rpcSettingsPageOnInfraIsEnabled: false, + [ICS_APPLY_FORM]: isMainnet, + [SURVEYS_SETUP_ENABLED]: isMainnet, + [DISABLE_DEPOSIT_DATA_VALIDATION]: false, }; }; diff --git a/config/get-config.ts b/config/get-config.ts index 31cc81fa2..ee0354de9 100644 --- a/config/get-config.ts +++ b/config/get-config.ts @@ -1,20 +1,20 @@ import { getPreConfig, PreConfigType } from './get-preconfig'; import * as cache from './groups/cache'; -import * as estimate from './groups/estimate'; import * as ipfs from './groups/ipfs'; import * as locale from './groups/locale'; import * as stake from './groups/stake'; -import * as withdrawalQueueEstimate from './groups/withdrawal-queue-estimate'; +import * as web3 from './groups/web3'; +import * as revalidation from './groups/revalidation'; export type ConfigType = { isClientSide: boolean; isServerSide: boolean; } & typeof cache & - typeof estimate & typeof ipfs & typeof locale & typeof stake & - typeof withdrawalQueueEstimate & + typeof web3 & + typeof revalidation & PreConfigType; export const getConfig = (): ConfigType => { @@ -23,11 +23,11 @@ export const getConfig = (): ConfigType => { isServerSide: typeof window === 'undefined', ...cache, - ...estimate, ...ipfs, ...locale, ...stake, - ...withdrawalQueueEstimate, + ...web3, + ...revalidation, // highest priority ...getPreConfig(), diff --git a/config/get-preconfig.ts b/config/get-preconfig.ts index e360200ff..59dddfa30 100644 --- a/config/get-preconfig.ts +++ b/config/get-preconfig.ts @@ -1,12 +1,16 @@ import getConfigNext from 'next/config'; import { default as dynamics } from './dynamics'; +import { MODULE_NAME, SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; +import { parseDefaultChain } from './helpers'; const { publicRuntimeConfig, serverRuntimeConfig } = getConfigNext(); -export type PreConfigType = { - BASE_PATH_ASSET: string; -} & typeof publicRuntimeConfig & - typeof dynamics; +export type PreConfigType = Omit & + typeof dynamics & { + module: MODULE_NAME; + defaultChain: SUPPORTED_CHAINS; + BASE_PATH_ASSET: string; + }; // `getPreConfig()` needs for internal using in 'config/groups/*' // Do not use `getPreConfig()` outside of 'config/groups/*' @@ -16,13 +20,19 @@ export const getPreConfig = (): PreConfigType => { : (serverRuntimeConfig.basePath ?? '') || (publicRuntimeConfig.basePath ?? ''); - return { + const config = { BASE_PATH_ASSET, ...publicRuntimeConfig, + module: MODULE_NAME[publicRuntimeConfig.module], ...(typeof window !== 'undefined' ? window.__env__ : dynamics), }; + + return { + ...config, + defaultChain: parseDefaultChain(config.defaultChain), + }; }; // `preConfig` needs for external internal in 'config/groups/*' diff --git a/config/get-secret-config.ts b/config/get-secret-config.ts index ca193c78c..2eac5aa01 100644 --- a/config/get-secret-config.ts +++ b/config/get-secret-config.ts @@ -1,23 +1,27 @@ import getConfigNext from 'next/config'; -import { type Modify, toBoolean } from './helpers'; +import { + type Modify, + parseDefaultChain, + parseUrlList, + toBoolean, +} from './helpers'; +import { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; const { serverRuntimeConfig } = getConfigNext(); export type SecretConfigType = Modify< typeof serverRuntimeConfig, { - defaultChain: number; + defaultChain: SUPPORTED_CHAINS; rpcUrls_1: [string, ...string[]]; - rpcUrls_17000: [string, ...string[]]; + rpcUrls_560048: [string, ...string[]]; clApiUrls_1: [string, ...string[]]; - clApiUrls_17000: [string, ...string[]]; + clApiUrls_560048: [string, ...string[]]; cspReportOnly: boolean; - subgraphRequestTimeout: number; - rateLimit: number; rateLimitTimeFrame: number; } @@ -32,31 +36,29 @@ export const getSecretConfig = (): SecretConfigType => { return { ...serverRuntimeConfig, - // Keep fallback as in 'env-dynamics.mjs' - defaultChain: Number(serverRuntimeConfig.defaultChain) || 17000, + defaultChain: parseDefaultChain(serverRuntimeConfig.defaultChain), // Hack: in the current implementation we can treat an empty array as a "tuple" (conditionally) - rpcUrls_1: (serverRuntimeConfig.rpcUrls_1?.split(',') ?? []) as [ + rpcUrls_1: parseUrlList(serverRuntimeConfig.rpcUrls_1) as [ string, ...string[], ], - rpcUrls_17000: (serverRuntimeConfig.rpcUrls_17000?.split(',') ?? []) as [ + rpcUrls_560048: parseUrlList(serverRuntimeConfig.rpcUrls_560048) as [ string, ...string[], ], - clApiUrls_1: (serverRuntimeConfig.clApiUrls_1?.split(',') ?? []) as [ + clApiUrls_1: parseUrlList(serverRuntimeConfig.clApiUrls_1) as [ + string, + ...string[], + ], + clApiUrls_560048: parseUrlList(serverRuntimeConfig.clApiUrls_560048) as [ string, ...string[], ], - clApiUrls_17000: (serverRuntimeConfig.clApiUrls_17000?.split(',') ?? - []) as [string, ...string[]], cspReportOnly: toBoolean(serverRuntimeConfig.cspReportOnly), - subgraphRequestTimeout: - Number(serverRuntimeConfig.subgraphRequestTimeout) || 5000, - rateLimit: Number(serverRuntimeConfig.rateLimit) || 100, rateLimitTimeFrame: Number(serverRuntimeConfig.rateLimitTimeFrame) || 60, // 1 minute; }; diff --git a/config/groups/cache.ts b/config/groups/cache.ts index 9d0a050e5..af8ae4255 100644 --- a/config/groups/cache.ts +++ b/config/groups/cache.ts @@ -1,42 +1,11 @@ import ms from 'ms'; -export const CACHE_STETH_APR_KEY = 'cache-steth-apr'; -export const CACHE_STETH_APR_TTL = ms('1h'); - -export const CACHE_SMA_STETH_APR_KEY = 'cache-sma-steth-apr'; -export const CACHE_SMA_STETH_APR_TTL = ms('30m'); - -export const CACHE_ETH_APR_KEY = 'cache-eth-apr'; -export const CACHE_ETH_APR_TTL = ms('1h'); - -export const CACHE_LIDO_STATS_KEY = 'cache-lido-stats'; -export const CACHE_LIDO_STATS_TTL = ms('1h'); - -export const CACHE_LIDO_SHORT_STATS_KEY = 'cache-short-lido-stats'; -export const CACHE_LIDO_SHORT_STATS_TTL = ms('1h'); - -export const CACHE_LIDO_HOLDERS_VIA_SUBGRAPHS_KEY = - 'cache-lido-holders-via-subgraphs'; -export const CACHE_LIDO_HOLDERS_VIA_SUBGRAPHS_TTL = ms('7d'); - -export const CACHE_LDO_STATS_KEY = 'cache-ldo-stats'; -export const CACHE_LDO_STATS_TTL = ms('1h'); - -export const CACHE_ETH_PRICE_KEY = 'cache-eth-price'; -export const CACHE_ETH_PRICE_TTL = ms('1m'); -export const CACHE_ETH_PRICE_HEADERS = - 'public, max-age=60, stale-if-error=1200, stale-while-revalidate=30'; - -export const CACHE_ONE_INCH_RATE_KEY = 'oneinch-rate'; -export const CACHE_ONE_INCH_RATE_TTL = ms('5m'); - -export const CACHE_TOTAL_SUPPLY_KEY = 'cache-total-supply'; -export const CACHE_TOTAL_SUPPLY_TTL = ms('1m'); -export const CACHE_TOTAL_SUPPLY_HEADERS = - 'public, max-age=60, stale-if-error=1200, stale-while-revalidate=30'; +export const CACHE_MIGALABS_RATE_KEY = 'cache-migalabs-rate'; +export const CACHE_MIGALABS_RATE_TTL = ms('3m'); +export const CACHE_MIGALABS_RATE_HEADERS = + 'public, max-age=180, stale-if-error=1200, stale-while-revalidate=30'; export const CACHE_DEFAULT_HEADERS = 'public, max-age=180, stale-if-error=1200, stale-while-revalidate=60'; -export const CACHE_REWARDS_HEADERS = +export const CACHE_VALIDATION_HEADERS = 'public, max-age=30, stale-if-error=1200, stale-while-revalidate=30'; -export const CACHE_DEFAULT_ERROR_HEADERS = 'no-store, must-revalidate'; diff --git a/config/groups/estimate.ts b/config/groups/estimate.ts deleted file mode 100644 index f3beb9e70..000000000 --- a/config/groups/estimate.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { parseEther } from '@ethersproject/units'; - -// account for gas estimation -// will always have >=0.001 ether, >=0.001 stETH, >=0.001 wstETH -// on Mainnet, Holesky -export const ESTIMATE_ACCOUNT = '0x87c0e047F4e4D3e289A56a36570D4CB957A37Ef1'; - -export const ESTIMATE_AMOUNT = parseEther('0.001'); diff --git a/config/groups/revalidation.ts b/config/groups/revalidation.ts new file mode 100644 index 000000000..37c996778 --- /dev/null +++ b/config/groups/revalidation.ts @@ -0,0 +1 @@ +export const DEFAULT_REVALIDATION = 60; // 1 minute diff --git a/config/groups/stake.ts b/config/groups/stake.ts index 484d835fd..87a7fad24 100644 --- a/config/groups/stake.ts +++ b/config/groups/stake.ts @@ -1,13 +1,4 @@ -import { BigNumber } from 'ethers'; -import { parseEther } from '@ethersproject/units'; -import { AddressZero } from '@ethersproject/constants'; - -import { IPFS_REFERRAL_ADDRESS } from './ipfs'; - -// Don't use here: -// import { config } from '../get-config'; -// otherwise you will get something like a cyclic error! -import { preConfig } from '../get-preconfig'; +import { parseEther } from 'viem'; // TODO: review this file @@ -20,14 +11,10 @@ export const SUBMIT_EXTRA_GAS_TRANSACTION_RATIO = 1.05; export const STETH_SUBMIT_GAS_LIMIT_DEFAULT = 90000; -export const STAKE_GASLIMIT_FALLBACK = BigNumber.from( +export const STAKE_GASLIMIT_FALLBACK = BigInt( Math.floor( STETH_SUBMIT_GAS_LIMIT_DEFAULT * SUBMIT_EXTRA_GAS_TRANSACTION_RATIO, ), ); -export const STAKE_WIDGET_METRIC_SUFFIX = '01'; - -export const STAKE_FALLBACK_REFERRAL_ADDRESS = preConfig.ipfsMode - ? IPFS_REFERRAL_ADDRESS - : AddressZero; +export const CSM_WIDGET_METRIC_SUFFIX = '01'; diff --git a/config/groups/web3.ts b/config/groups/web3.ts new file mode 100644 index 000000000..6fb70c7bf --- /dev/null +++ b/config/groups/web3.ts @@ -0,0 +1,10 @@ +// interval in ms for RPC event polling for token balance and tx updates +export const PROVIDER_POLLING_INTERVAL = 12_000; +// how long in ms to wait for RPC batching(multicall and provider) +export const PROVIDER_BATCH_TIME = 150; +// max batch +export const PROVIDER_MAX_BATCH = 20; +// AA transaction polling timeout(ms) +export const AA_TX_POLLING_TIMEOUT = 180_000; // 3 minutes + +export const MAX_BLOCK_RANGE_FOR_EVENTS = 10_000; diff --git a/config/groups/withdrawal-queue-estimate.ts b/config/groups/withdrawal-queue-estimate.ts deleted file mode 100644 index a69fc6757..000000000 --- a/config/groups/withdrawal-queue-estimate.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BigNumber } from 'ethers'; - -// fallback gas limits per 1 withdraw request -export const WITHDRAWAL_QUEUE_REQUEST_STETH_PERMIT_GAS_LIMIT_DEFAULT = - BigNumber.from(255350); -export const WITHDRAWAL_QUEUE_REQUEST_WSTETH_PERMIT_GAS_LIMIT_DEFAULT = - BigNumber.from(312626); - -export const WITHDRAWAL_QUEUE_REQUEST_STETH_APPROVED_GAS_LIMIT_DEFAULT = - BigNumber.from(228163); -export const WITHDRAWAL_QUEUE_REQUEST_WSTETH_APPROVED_GAS_LIMIT_DEFAULT = - BigNumber.from(280096); - -export const WITHDRAWAL_QUEUE_CLAIM_GAS_LIMIT_DEFAULT = BigNumber.from(89818); diff --git a/config/helpers.ts b/config/helpers.ts index 5f505bba2..676cab9d4 100644 --- a/config/helpers.ts +++ b/config/helpers.ts @@ -1,5 +1,24 @@ +import { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; + export type Modify = Omit & R; +// Keep fallback as in 'env-dynamics.mjs' (Hoodi) +const FALLBACK_CHAIN = 560048 as SUPPORTED_CHAINS; + +// An unsupported DEFAULT_CHAIN crashes per-chain SDK lookups +// (e.g. CURVE_ID_OPERATOR_TYPE[chainId][module]) on nearly every render, +// so validate at parse time and fall back to Hoodi +export const parseDefaultChain = (val: unknown): SUPPORTED_CHAINS => { + const parsed = Number(val) || FALLBACK_CHAIN; + if ((SUPPORTED_CHAINS as readonly number[]).includes(parsed)) { + return parsed as SUPPORTED_CHAINS; + } + console.error( + `[config] Unsupported defaultChain "${String(val)}", falling back to ${FALLBACK_CHAIN} (Hoodi). Supported chains: ${SUPPORTED_CHAINS.join(', ')}`, + ); + return FALLBACK_CHAIN; +}; + export const toBoolean = (val: any) => { return ( val?.toLowerCase?.() === 'true' || @@ -7,3 +26,12 @@ export const toBoolean = (val: any) => { Number.parseInt(val, 10) === 1 ); }; + +// Parse a comma-separated list of URLs, trimming whitespace and stripping +// trailing slashes. Some RPC/CL providers reject requests to paths ending in +// `/` even though the URL is visually identical. +export const parseUrlList = (val?: string): string[] => + val + ?.split(',') + .map((s) => s.trim().replace(/\/+$/, '')) + .filter(Boolean) ?? []; diff --git a/config/rpc/cl.ts b/config/rpc/cl.ts index 14f0e2103..02e19416e 100644 --- a/config/rpc/cl.ts +++ b/config/rpc/cl.ts @@ -1,8 +1,6 @@ import { useCallback } from 'react'; import invariant from 'tiny-invariant'; -import { useSDK } from '@lido-sdk/react'; -import { CHAINS } from 'consts/chains'; import { API_ROUTES } from 'consts/api'; // Don't use absolute import here! @@ -11,9 +9,11 @@ import { API_ROUTES } from 'consts/api'; // ''' // otherwise you will get something like a cyclic error! import { config } from '../get-config'; - import { useUserConfig } from '../user-config'; +import { useDappStatus } from 'modules/web3'; +import { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; + export const getBackendApiPath = (chainId: string | number): string => { const BASE_URL = typeof window === 'undefined' ? '' : window.location.origin; return `${BASE_URL}/${API_ROUTES.CL}/${chainId}`; @@ -23,14 +23,10 @@ export const useGetClApiUrlByChainId = () => { const userConfig = useUserConfig(); return useCallback( - (chainId: CHAINS) => { - // This condition is needed because in 'providers/web3.tsx' we add `wagmiChains.polygonMumbai` to supportedChains as a workaround. - // polygonMumbai (80001) may cause an invariant throwing. - if (!userConfig.supportedChainIds.includes(chainId)) { + (chainId: SUPPORTED_CHAINS) => { + if (chainId !== userConfig.defaultChain) { // Has no effect on functionality. Just a fix. // Return empty string as a stub - // (see: 'providers/web3.tsx' --> jsonRpcBatchProvider --> getStaticRpcBatchProvider) - // TODO: check this return ''; } @@ -51,6 +47,6 @@ export const useGetClApiUrlByChainId = () => { }; export const useClApiUrl = () => { - const { chainId } = useSDK(); - return useGetClApiUrlByChainId()(chainId as number); + const { chainId } = useDappStatus(); + return useGetClApiUrlByChainId()(chainId); }; diff --git a/config/rpc/index.ts b/config/rpc/index.ts index 93fa8c8e6..1148ecf7c 100644 --- a/config/rpc/index.ts +++ b/config/rpc/index.ts @@ -1,8 +1,6 @@ import { useCallback } from 'react'; import invariant from 'tiny-invariant'; -import { useSDK } from '@lido-sdk/react'; -import { CHAINS } from 'consts/chains'; import { API_ROUTES } from 'consts/api'; // Don't use absolute import here! @@ -12,6 +10,8 @@ import { API_ROUTES } from 'consts/api'; // otherwise you will get something like a cyclic error! import { config } from '../get-config'; +import { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; import { useUserConfig } from '../user-config'; export const getBackendRPCPath = (chainId: string | number): string => { @@ -23,17 +23,11 @@ export const useGetRpcUrlByChainId = () => { const userConfig = useUserConfig(); return useCallback( - (chainId: CHAINS) => { - // This condition is needed because in 'providers/web3.tsx' we add `wagmiChains.polygonMumbai` to supportedChains as a workaround. - // polygonMumbai (80001) may cause an invariant throwing. - // And we always need Mainnet RPC for some requests, e.g. ETH to USD price, ENS lookup. - if ( - chainId !== CHAINS.Mainnet && - !userConfig.supportedChainIds.includes(chainId) - ) { + (chainId: SUPPORTED_CHAINS) => { + // We always need Mainnet RPC for some requests, e.g. ETH to USD price, ENS lookup. + if (chainId !== CHAINS.Mainnet && chainId !== userConfig.defaultChain) { // Has no effect on functionality. Just a fix. // Return empty string as a stub - // (see: 'providers/web3.tsx' --> jsonRpcBatchProvider --> getStaticRpcBatchProvider) return ''; } @@ -54,8 +48,3 @@ export const useGetRpcUrlByChainId = () => { [userConfig], ); }; - -export const useRpcUrl = () => { - const { chainId } = useSDK(); - return useGetRpcUrlByChainId()(chainId as number); -}; diff --git a/config/user-config/context-hook.tsx b/config/user-config/context-hook.tsx index 3fddb22c2..9dfa5a76e 100644 --- a/config/user-config/context-hook.tsx +++ b/config/user-config/context-hook.tsx @@ -1,31 +1,22 @@ import { useMemo, useState, useCallback } from 'react'; -import { useLocalStorage } from '@lido-sdk/react'; - -import { CHAINS } from 'consts/chains'; - import { getUserConfigDefault } from './utils'; import { UserConfigDefaultType } from './types'; - -const STORAGE_USER_CONFIG = 'lido-user-config'; - -type SavedUserConfig = { - rpcUrls: Partial>; - clApiUrls: Partial>; -}; +import { + STORAGE_USER_CONFIG, + DEFAULT_SAVED_USER_CONFIG as DEFAULT_STATE, + SavedUserConfig, +} from './saved-config'; +import { useLocalStorage } from 'shared/hooks/use-local-storage'; export type UserConfigContextType = UserConfigDefaultType & { savedUserConfig: SavedUserConfig; setSavedUserConfig: (config: SavedUserConfig) => void; + resetSavedUserConfig: () => void; isWalletConnectionAllowed: boolean; setIsWalletConnectionAllowed: (isAllowed: boolean) => void; }; -const DEFAULT_STATE: SavedUserConfig = { - rpcUrls: {}, - clApiUrls: {}, -}; - export const useUserConfigContext = () => { const [restoredSettings, setLocalStorage] = useLocalStorage( STORAGE_USER_CONFIG, @@ -35,8 +26,10 @@ export const useUserConfigContext = () => { const [isWalletConnectionAllowed, setIsWalletConnectionAllowed] = useState(true); - const [savedUserConfig, setSavedUserConfig] = - useState(restoredSettings); + const [savedUserConfig, setSavedUserConfig] = useState({ + ...DEFAULT_STATE, + ...restoredSettings, + }); const setSavedConfigAndRemember = useCallback( (config: SavedUserConfig) => { @@ -46,6 +39,11 @@ export const useUserConfigContext = () => { [setLocalStorage], ); + const resetSavedUserConfig = useCallback(() => { + setLocalStorage(DEFAULT_STATE); + setSavedUserConfig(DEFAULT_STATE); + }, [setLocalStorage]); + return useMemo(() => { const userConfigDefault = getUserConfigDefault(); @@ -53,8 +51,14 @@ export const useUserConfigContext = () => { ...userConfigDefault, savedUserConfig, setSavedUserConfig: setSavedConfigAndRemember, + resetSavedUserConfig, isWalletConnectionAllowed, setIsWalletConnectionAllowed, }; - }, [isWalletConnectionAllowed, savedUserConfig, setSavedConfigAndRemember]); + }, [ + isWalletConnectionAllowed, + savedUserConfig, + setSavedConfigAndRemember, + resetSavedUserConfig, + ]); }; diff --git a/config/user-config/index.ts b/config/user-config/index.ts index 16d87cf14..b614a3109 100644 --- a/config/user-config/index.ts +++ b/config/user-config/index.ts @@ -1,4 +1,5 @@ export * from './hooks'; export * from './context-hook'; +export * from './saved-config'; export * from './types'; export * from './utils'; diff --git a/config/user-config/saved-config.ts b/config/user-config/saved-config.ts new file mode 100644 index 000000000..2c044d70f --- /dev/null +++ b/config/user-config/saved-config.ts @@ -0,0 +1,35 @@ +import type { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; + +// QA overrides persisted in localStorage under `lido-user-config`. +// Shared by the writer (qa-config form via the user-config context) and by +// non-React readers (e.g. surveys-sdk transport) that resolve config at module +// load. Keep the key and shape here so both sides stay in sync. +export const STORAGE_USER_CONFIG = 'lido-user-config'; + +export type SavedUserConfig = { + rpcUrls: Partial>; + clApiUrls: Partial>; + ipfsGateways: string[]; + surveyApiUrl?: string; +}; + +export const DEFAULT_SAVED_USER_CONFIG: SavedUserConfig = { + rpcUrls: {}, + clApiUrls: {}, + ipfsGateways: [], +}; + +// SSR-safe synchronous read of the saved QA overrides. Returns defaults during +// SSR or when nothing is stored / parsing fails. Used by modules that resolve +// their config once at load time — these pick up changes only after a reload, +// matching the qa-config form's "Reload the page to apply" behavior. +export const readSavedUserConfig = (): SavedUserConfig => { + if (typeof window === 'undefined') return DEFAULT_SAVED_USER_CONFIG; + try { + const item = window.localStorage.getItem(STORAGE_USER_CONFIG); + if (!item || item === 'undefined') return DEFAULT_SAVED_USER_CONFIG; + return { ...DEFAULT_SAVED_USER_CONFIG, ...JSON.parse(item) }; + } catch { + return DEFAULT_SAVED_USER_CONFIG; + } +}; diff --git a/config/user-config/types.ts b/config/user-config/types.ts index f4c09a4fc..fd355dd96 100644 --- a/config/user-config/types.ts +++ b/config/user-config/types.ts @@ -1,11 +1,12 @@ -import { CHAINS } from 'consts/chains'; +import { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; export type UserConfigDefaultType = { - defaultChain: number; - supportedChainIds: number[]; + defaultChain: SUPPORTED_CHAINS; prefillUnsafeElRpcUrls: { [CHAINS.Mainnet]: string[]; - [CHAINS.Holesky]: string[]; + [CHAINS.Hoodi]: string[]; }; walletconnectProjectId: string | undefined; + defaultIpfsGateways: string[]; }; diff --git a/config/user-config/utils.ts b/config/user-config/utils.ts index bb8eaeb42..0cf9c3448 100644 --- a/config/user-config/utils.ts +++ b/config/user-config/utils.ts @@ -3,19 +3,18 @@ // import { config } from 'config'; // ''' // otherwise you will get something like a cyclic error! +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; import { config } from '../get-config'; import { UserConfigDefaultType } from './types'; -import { CHAINS } from 'consts/chains'; - export const getUserConfigDefault = (): UserConfigDefaultType => { return { - defaultChain: Number(config.defaultChain), - supportedChainIds: config.supportedChains, + defaultChain: config.defaultChain, prefillUnsafeElRpcUrls: { [CHAINS.Mainnet]: config.prefillUnsafeElRpcUrls1, - [CHAINS.Holesky]: config.prefillUnsafeElRpcUrls17000, + [CHAINS.Hoodi]: config.prefillUnsafeElRpcUrls560048, }, walletconnectProjectId: config.walletconnectProjectId, + defaultIpfsGateways: config.ipfsGateways, }; }; diff --git a/consts/aggregator.ts b/consts/aggregator.ts deleted file mode 100644 index 5da55d340..000000000 --- a/consts/aggregator.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { CHAINS } from '@lido-sdk/constants'; -import invariant from 'tiny-invariant'; - -// https://etherscan.io/address/0xcfe54b5cd566ab89272946f602d76ea879cab4a8 -export const AGGREGATOR_STETH_USD_PRICE_FEED_BY_NETWORK: { - [key in CHAINS]?: string; -} = { - [CHAINS.Mainnet]: '0xcfe54b5cd566ab89272946f602d76ea879cab4a8', -}; - -// Chainlink: STETH/USD Price Feed -// https://data.chain.link/ethereum/mainnet/crypto-usd/steth-usd -export const getAggregatorStEthUsdPriceFeedAddress = ( - chainId: CHAINS, -): string => { - const address = AGGREGATOR_STETH_USD_PRICE_FEED_BY_NETWORK[chainId]; - invariant(address, 'chain is not supported'); - return address; -}; diff --git a/consts/alerts.ts b/consts/alerts.ts new file mode 100644 index 000000000..b7343bc79 --- /dev/null +++ b/consts/alerts.ts @@ -0,0 +1 @@ +export const ALERT_FEE_RECIPIENT_DISMISS_HOURS = 10; diff --git a/consts/api.ts b/consts/api.ts index 45256248c..5d042a5d3 100644 --- a/consts/api.ts +++ b/consts/api.ts @@ -1,13 +1,7 @@ -export const ETHPLORER_TOKEN_ENDPOINT = - 'https://api.ethplorer.io/getTokenInfo/'; - -export const HEALTHY_RPC_SERVICES_ARE_OVER = 'Healthy RPC services are over!'; - -// TODO: review - export const enum API_ROUTES { - ETH_PRICE = 'api/eth-price', + PERFORMANCE = 'api/performance', RPC = 'api/rpc', CL = 'api/cl', METRICS = 'api/metrics', + VALIDATION = 'api/validation', } diff --git a/consts/chains.ts b/consts/chains.ts index 1c5e10122..6a9512000 100644 --- a/consts/chains.ts +++ b/consts/chains.ts @@ -1,4 +1,12 @@ -export const enum CHAINS { - Mainnet = 1, - Holesky = 17000, -} +import { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; + +type ChainInfo = { + name: string; + color: string; +}; + +export const CHAIN_METADATA: Record = { + [CHAINS.Mainnet]: { name: 'Mainnet', color: '#29b6af' }, + [CHAINS.Hoodi]: { name: 'Hoodi', color: '#AA346A' }, +}; diff --git a/consts/csm-constants.ts b/consts/csm-constants.ts deleted file mode 100644 index e5d9f8d10..000000000 --- a/consts/csm-constants.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { CHAINS } from '@lido-sdk/constants'; -import { config } from 'config'; -import { HexString } from 'shared/keys'; -import { Address } from 'wagmi'; - -export const KEYS_UPLOAD_TX_LIMIT = 25; - -type CsmContract = - | 'CSAccounting' - | 'CSEarlyAdoption' - | 'CSFeeDistributor' - | 'CSFeeOracle' - | 'CSModule' - | 'CSVerifier' - | 'ExitBusOracle' - | 'StakingRouter'; - -type CsmConstants = { - contracts: Record; - deploymentBlockNumber: HexString; - stakingModuleId: number; - withdrawalCredentials: Address; - retentionPeriodMins: number; - slotsPerFrame: number; -}; - -export const CONSTANTS_BY_NETWORK: Partial> = { - [CHAINS.Mainnet]: { - contracts: { - CSAccounting: '0x4d72BFF1BeaC69925F8Bd12526a39BAAb069e5Da', - CSEarlyAdoption: '0x3D5148ad93e2ae5DedD1f7A8B3C19E7F67F90c0E', - CSFeeDistributor: '0xD99CC66fEC647E68294C6477B40fC7E0F6F618D0', - CSFeeOracle: '0x4D4074628678Bd302921c20573EEa1ed38DdF7FB', - CSModule: '0xdA7dE2ECdDfccC6c3AF10108Db212ACBBf9EA83F', - CSVerifier: '0x3Dfc50f22aCA652a0a6F28a0F892ab62074b5583', - ExitBusOracle: '0x0De4Ea0184c2ad0BacA7183356Aea5B8d5Bf5c6e', - StakingRouter: '0xFdDf38947aFB03C621C71b06C9C70bce73f12999', - }, - deploymentBlockNumber: '0x13f7326', - stakingModuleId: 3, - withdrawalCredentials: '0xB9D7934878B5FB9610B3fE8A5e441e8fad7E293f', - retentionPeriodMins: 80_640, // 8 weeks - slotsPerFrame: 32 * 225 * 28, // 28 days - }, - [CHAINS.Holesky]: { - contracts: { - CSAccounting: '0xc093e53e8F4b55A223c18A2Da6fA00e60DD5EFE1', - CSEarlyAdoption: '0x71E92eA77C198a770d9f33A03277DbeB99989660', - CSFeeDistributor: '0xD7ba648C8F72669C6aE649648B516ec03D07c8ED', - CSFeeOracle: '0xaF57326C7d513085051b50912D51809ECC5d98Ee', - CSModule: '0x4562c3e63c2e586cD1651B958C22F88135aCAd4f', - CSVerifier: '0x6DcA479178E6Ae41CCEB72a88FfDaa3e10E83CB7', - ExitBusOracle: '0xffDDF7025410412deaa05E3E1cE68FE53208afcb', - StakingRouter: '0xd6EbF043D30A7fe46D1Db32BA90a0A51207FE229', - }, - deploymentBlockNumber: '0x1b143a', - stakingModuleId: 4, - withdrawalCredentials: '0xF0179dEC45a37423EAD4FaD5fCb136197872EAd9', - retentionPeriodMins: 80_640, // 8 weeks - slotsPerFrame: 32 * 225 * 7, // 7 days - }, -}; - -export const getCsmConstants = ( - chainId: CHAINS | undefined = config.defaultChain, -) => { - const constants = CONSTANTS_BY_NETWORK[chainId]; - if (!constants) { - throw new Error(`CSM constants for chain [${chainId}] are not specified`); - } - return constants; -}; - -export const getCsmContractAddress = ( - chainId: CHAINS | undefined, - contract: CsmContract, -): Address => getCsmConstants(chainId).contracts[contract]; - -export const getCsmContractAddressGetter = - (contract: CsmContract) => (chainId: CHAINS | undefined) => - getCsmContractAddress(chainId, contract); diff --git a/consts/external-links.ts b/consts/external-links.ts index 700bd4025..761945dd4 100644 --- a/consts/external-links.ts +++ b/consts/external-links.ts @@ -1,92 +1,111 @@ -import { CHAINS } from '@lido-sdk/constants'; +import { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; import { config } from 'config'; +import { isModuleCM, isModuleCSM } from './module'; export const CSM_MAINNET_LINK = 'https://csm.lido.fi/'; export const CSM_TESTNET_LINK = 'https://csm.testnet.fi/'; +export const CM_MAINNET_LINK = 'https://cm.lido.fi/'; +export const CM_TESTNET_LINK = 'https://cm.testnet.fi/'; +// Documentation links +export const EXTENDED_MODE_LINK = + 'https://docs.lido.fi/run-on-lido/csm/lido-csm-widget/operator-roles#extended-mode'; +export const UNBONDED_VALIDATORS_LINK = + 'https://docs.lido.fi/run-on-lido/csm/troubleshooting/unbonded-validators'; +export const MEV_STEALING_LINK = + 'https://docs.lido.fi/run-on-lido/csm/troubleshooting/mev-stealing'; +export const PERFORMANCE_TIPS_LINK = + 'https://docs.lido.fi/run-on-lido/csm/best-practices/maximizing-uptime-and-performance/'; export const HOW_TO_EXIT_VALIDATOR_LINK = - 'https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm/exiting-csm-validators'; - + 'https://docs.lido.fi/run-on-lido/csm/lido-csm-widget/exiting-csm-validators/exit-using-validator-keystores'; export const ABOUT_DEPOSIT_DATA_LINK = - 'https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm'; - + 'https://docs.lido.fi/run-on-lido/csm/node-setup/'; export const HOW_TO_GENERATE_DEPOSIT_DATA_LINK = - 'https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm#key-settings-to-note'; - + 'https://docs.lido.fi/run-on-lido/csm/generating-validator-keys/'; export const PREPARE_HARDWARE_LINK = 'https://dvt-homestaker.stakesaurus.com/hardware-and-systems-setup/hardware-and-system-requirements'; +export const UPLOAD_DEPOSIT_DATA_LINK = + 'https://docs.lido.fi/run-on-lido/csm/lido-csm-widget/upload-remove-view-validator-keys#upload-keys'; +export const SUBSCRIBE_EVENTS_LINK = + 'https://docs.lido.fi/run-on-lido/csm/alerts-and-monitoring/expert-custom-alerts'; +export const OPERATOR_TYPES_LINK = + 'https://docs.lido.fi/staking-modules/csm/join-csm/#node-operator-types'; +export const CM_BOND_AMOUNTS_LINK = + 'https://docs.lido.fi/run-on-lido/cm-v2/bond-and-key-management#bond-amounts'; +export const FEE_RECIPIENT_LINK = + 'https://docs.lido.fi/run-on-lido/csm/troubleshooting/setting-the-fee-recipient-for-csm-validators/#change-fee-recipient-on-existing-validator-keys'; + +// Lido Operator Portal links +export const LIDO_OPERATOR_PORTAL_BASE = + 'https://operatorportal.lido.fi/modules/community-staking-module'; +export const LIDO_OPERATOR_PORTAL_CM = + 'https://operatorportal.lido.fi/modules/curated-module-v2-1'; +export const LIDO_OPERATOR_PORTAL_BONDS_INFO = `${LIDO_OPERATOR_PORTAL_BASE}#block-e4a6daadca12480d955524247f03f380`; +export const LIDO_OPERATOR_PORTAL_PERFORMANCE_ORACLE = `${LIDO_OPERATOR_PORTAL_BASE}#block-c6dc8d00f13243fcb17de3fa07ecc52c`; +export const LIDO_OPERATOR_PORTAL_DEPOSITS_FLOW = `${LIDO_OPERATOR_PORTAL_BASE}#block-90b8ff95edc64cf7a051584820219616`; + +// Lido Execution Layer Rewards Vault +export const LIDO_REWARDS_VAULT_LINK = + 'https://etherscan.io/address/0x388C818CA8B9251b393131C08a736A67ccB19297'; type ExternalLinksConstants = { - earlyAdoptionTree: string; rewardsTree: string; - - earlyAdoptionSources: string; - earlyAdoptionAbout: string; feedbackForm: string; stakeWidget: string; + landing?: string; beaconchain: string; feesMonitoring: string; operatorsWidget: string; - beaconchainDashboard: string; ratedExplorer: string; - ethseerDashboard?: string; - subscribeEvents: string; + migalabsDashboard: string; + migalabs: string; keysApi: string; surveyApi: string; }; -export const EXTERNAL_LINKS_BY_NETWORK: Partial< - Record +export const EXTERNAL_LINKS_BY_NETWORK: Record< + SUPPORTED_CHAINS, + ExternalLinksConstants > = { [CHAINS.Mainnet]: { - earlyAdoptionTree: - 'https://raw.githubusercontent.com/lidofinance/community-staking-module/v1.0/artifacts/mainnet/early-adoption/merkle-tree.json', rewardsTree: 'https://raw.githubusercontent.com/lidofinance/csm-rewards/mainnet/tree.json', - earlyAdoptionSources: - 'https://github.com/lidofinance/community-staking-module/blob/v1.0/artifacts/mainnet/early-adoption/addresses.json', - earlyAdoptionAbout: - 'https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22', feedbackForm: 'https://forms.gle/GL9RYeV2g4px58Sv8', stakeWidget: 'https://stake.lido.fi', + landing: isModuleCSM ? 'https://lido.fi/csm' : LIDO_OPERATOR_PORTAL_CM, feesMonitoring: 'https://fees-monitoring.lido.fi', operatorsWidget: 'https://operators.lido.fi', beaconchain: 'https://beaconcha.in', - beaconchainDashboard: 'https://v2-beta-mainnet.beaconcha.in/dashboard', ratedExplorer: 'https://explorer.rated.network', - ethseerDashboard: 'https://ethseer.io', - subscribeEvents: 'https://docs.lido.fi/staking-modules/csm/guides/events', + migalabsDashboard: 'https://migalabs.io/entities', + migalabs: 'https://migalabs.io', keysApi: 'https://keys-api.lido.fi', - surveyApi: 'https://csm-surveys-api-mainnet.up.railway.app', + surveyApi: 'https://csm-survey-api.lido.tools', }, - [CHAINS.Holesky]: { - earlyAdoptionTree: - 'https://raw.githubusercontent.com/lidofinance/community-staking-module/v1.0/artifacts/holesky/early-adoption/merkle-tree.json', + [CHAINS.Hoodi]: { rewardsTree: - 'https://raw.githubusercontent.com/lidofinance/csm-rewards/holesky/tree.json', - earlyAdoptionSources: - 'https://github.com/lidofinance/community-staking-module/blob/v1.0/artifacts/holesky/early-adoption/addresses.json', - earlyAdoptionAbout: - 'https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22', - feedbackForm: 'https://forms.gle/ZBUqbykaZokJLf4M7', - stakeWidget: 'https://stake-holesky.testnet.fi', + 'https://raw.githubusercontent.com/lidofinance/csm-rewards/hoodi/tree.json', + feedbackForm: isModuleCM + ? 'https://forms.gle/Lhh4fGXvx7Gwcd6e7' + : 'https://forms.gle/ZBUqbykaZokJLf4M7', + stakeWidget: 'https://stake-hoodi.testnet.fi', + landing: isModuleCSM ? 'https://testnet.fi/csm' : 'https://testnet.fi/cm', - feesMonitoring: 'https://fees-monitoring-holesky.testnet.fi', - operatorsWidget: 'https://operators-holesky.testnet.fi', - beaconchain: 'https://holesky.beaconcha.in', - beaconchainDashboard: 'https://v2-beta-holesky.beaconcha.in/dashboard', - ratedExplorer: 'https://explorer.rated.network', - subscribeEvents: 'https://docs.lido.fi/staking-modules/csm/guides/events', - keysApi: 'https://keys-api-holesky.testnet.fi', - surveyApi: 'https://csm-surveys-api-testnet.up.railway.app', + feesMonitoring: 'https://fees-monitoring-hoodi.testnet.fi', + operatorsWidget: 'https://operators-hoodi.testnet.fi', + beaconchain: 'https://hoodi.beaconcha.in', + ratedExplorer: '', + migalabsDashboard: '', + migalabs: 'https://migalabs.io', + keysApi: 'https://keys-api-hoodi.testnet.fi', + surveyApi: 'https://csm-survey-api-hoodi.lido.tools', }, }; -export const getExternalLinks = ( - chainId: CHAINS | undefined = config.defaultChain, -) => { +export const getExternalLinks = (chainId = config.defaultChain) => { const links = EXTERNAL_LINKS_BY_NETWORK[chainId]; if (!links) { throw new Error(`ExternalLinks for chain [${chainId}] are not specified`); diff --git a/consts/index.ts b/consts/index.ts new file mode 100644 index 000000000..9a56239e4 --- /dev/null +++ b/consts/index.ts @@ -0,0 +1,16 @@ +export * from './alerts'; +export * from './api'; +export * from './chains'; +export * from './external-links'; +export * from './keys'; +export * from './matomo-click-events'; +export * from './matomo-wallets-events'; +export * from './metrics'; +export * from './module'; +export * from './operator-type-metadata'; +export * from './react-query-strategies'; +export * from './ref-mapping'; +export * from './roles'; +export * from './text'; +export * from './tokens'; +export * from './urls'; diff --git a/consts/key-status.ts b/consts/key-status.ts deleted file mode 100644 index e89008771..000000000 --- a/consts/key-status.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const KEY_STATUS = { - NON_QUEUED: 'NON_QUEUED', - DEPOSITABLE: 'DEPOSITABLE', - ACTIVATION_PENDING: 'ACTIVATION_PENDING', - ACTIVE: 'ACTIVE', - EXITING: 'EXITING', - WITHDRAWAL_PENDING: 'WITHDRAWAL_PENDING', - WITHDRAWN: 'WITHDRAWN', - - UNCHECKED: 'UNCHECKED', - DUPLICATED: 'DUPLICATED', - INVALID: 'INVALID', - - UNBONDED: 'UNBONDED', - EXIT_REQUESTED: 'EXIT_REQUESTED', - STUCK: 'STUCK', - SLASHED: 'SLASHED', -} as const; - -export type KEY_STATUS = keyof typeof KEY_STATUS; diff --git a/consts/keys.ts b/consts/keys.ts new file mode 100644 index 000000000..d882b9013 --- /dev/null +++ b/consts/keys.ts @@ -0,0 +1 @@ +export const KEYS_UPLOAD_TX_LIMIT = 25; diff --git a/consts/matomo-click-events.ts b/consts/matomo-click-events.ts index 312931b5d..8c706f358 100644 --- a/consts/matomo-click-events.ts +++ b/consts/matomo-click-events.ts @@ -1,96 +1,164 @@ import { MatomoEventType } from '@lidofinance/analytics-matomo'; +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { config } from 'config'; -export const MATOMO_APP_NAME = 'CSM_Widget'; -export const MATOMO_APP_PREFIX = 'csm_widget'; - -export const prefixed = (template: TemplateStringsArray, ...args: string[]) => { - return `${MATOMO_APP_PREFIX}_${template.reduce((a, c, i) => a + c + (args[i] ?? ''), '').toLowerCase()}`; +export const MATOMO_APP_NAME = { + [MODULE_NAME.CSM]: 'CSM_Widget', + [MODULE_NAME.CM]: 'CM_Widget', +}; +export const MATOMO_APP_PREFIX = { + [MODULE_NAME.CSM]: 'csm_widget', + [MODULE_NAME.CM]: 'cm_widget', }; +// Helper functions to reduce duplication in event definitions +export const createEvent = ( + description: string, + eventKey: string, +): MatomoEventType => [ + MATOMO_APP_NAME[config.module], + description, + `${MATOMO_APP_PREFIX[config.module]}_${eventKey.toLowerCase()}`, +]; + export const enum MATOMO_CLICK_EVENTS_TYPES { // Welcome connectWallet = 'connectWallet', + disconnectWallet = 'disconnectWallet', + clickShowMoreWallets = 'clickShowMoreWallets', + clickShowLessWallets = 'clickShowLessWallets', connectAsNodeOperator = 'connectAsNodeOperator', connectToBecomeNodeOperator = 'connectToBecomeNodeOperator', welcomeDetailedLink = 'welcomeDetailedLink', - earlyAdoptionLearnMore = 'earlyAdoptionLearnMore', - earlyAdoptionCuratedList = 'earlyAdoptionCuratedList', // Starter Pack starterPackCreateNodeOperator = 'starterPackCreateNodeOperator', - consumedEarlyAdoptionLearnMore = 'consumedEarlyAdoptionLearnMore', - notEligibleEarlyAdoptionLearnMore = 'notEligibleEarlyAdoptionLearnMore', partnerDappnode = 'partnerDappnode', partnerSedge = 'partnerSedge', partnerStereum = 'partnerStereum', partnerEthdocker = 'partnerEthdocker', starterPackCSMLink = 'starterPackCSMLink', starterPackBondLink = 'starterPackBondLink', - starterPackHadwareLink = 'starterPackHadwareLink', + starterPackHardwareLink = 'starterPackHardwareLink', starterPackSetupValidatorLink = 'starterPackSetupValidatorLink', starterPackGenerateKeysLink = 'starterPackGenerateKeysLink', + operatorTypeModalJoinPermissionless = 'operatorTypeModalJoinPermissionless', + operatorTypeModalApplyIcs = 'operatorTypeModalApplyIcs', + operatorTypeModalApplyIdvtc = 'operatorTypeModalApplyIdvtc', + operatorTypeModalCreateIcs = 'operatorTypeModalCreateIcs', + operatorTypeModalCreateIdvtc = 'operatorTypeModalCreateIdvtc', // Forms - howBondIsCalculated = 'howBondIsCalculated', depositDataLearnMore = 'depositDataLearnMore', howToClaimEth = 'howToClaimEth', customAddressDescription = 'customAddressDescription', - managerAdressPermissionTypeDescription = 'managerAdressPermissionTypeDescription', + managerAddressPermissionTypeDescription = 'managerAddressPermissionTypeDescription', createSuccessKeysTab = 'createSuccessKeysTab', createSuccessBeaconchainDashboard = 'createSuccessBeaconchainDashboard', createSuccessBeaconchain = 'createSuccessBeaconchain', createSuccessSubscribeEvents = 'createSuccessSubscribeEvents', otherModuleLink = 'otherModuleLink', - splitsOrgDocumentation = 'splitsOrgDocumentation', howToClaimEthSuccessLink = 'howToClaimEthSuccessLink', // Common etherscanTxLink = 'etherscanTxLink', etherscanAddressLink = 'etherscanAddressLink', beaconchainPubkeyLink = 'beaconchainPubkeyLink', - feedbackFormLink = 'feedbackFormLink', - tryCsmOtherNetworkLink = 'tryCsmOtherNetworkLink', + migalabsPubkeyLink = 'migalabsPubkeyLink', + tryOtherNetworkLink = 'tryOtherNetworkLink', stakeShareLimitLinkBanner = 'stakeShareLimitLinkBanner', + faqItemLink = 'faqItemLink', // Key status comment howToExitLinkComment = 'howToExitLinkComment', whenValidatorBecomeActiveLinkComment = 'whenValidatorBecomeActiveLinkComment', whenValidatorBecomeWithdrawnLinkComment = 'whenValidatorBecomeWithdrawnLinkComment', stakeShareLimitLinkComment = 'stakeShareLimitLinkComment', // Alerts - howLearnCsmClose = 'howLearnCsmClose', howToExitLinkRequestToExitAlert = 'howToExitLinkRequestToExitAlert', - howToExitLinkStuckKeysAlert = 'howToExitLinkStuckKeysAlert', normalizeQueueLinkAlert = 'normalizeQueueLinkAlert', unlockBondLinkAlert = 'unlockBondLinkAlert', + expiredLockedBondLinkAlert = 'expiredLockedBondLinkAlert', + claimIcsLinkAlert = 'claimIcsLinkAlert', + claimIdvtcLinkAlert = 'claimIdvtcLinkAlert', + feeRecipientDocsLink = 'feeRecipientDocsLink', + feeRecipientDismissButton = 'feeRecipientDismissButton', + wrappedAlertClose = 'wrappedAlertClose', + wrappedAlertLink = 'wrappedAlertLink', + wrappedLetsGo = 'wrappedLetsGo', + wrappedRepeat = 'wrappedRepeat', + wrappedShareOpen = 'wrappedShareOpen', + wrappedShareCopy = 'wrappedShareCopy', + wrappedShareNative = 'wrappedShareNative', + wrappedShareDownload = 'wrappedShareDownload', + wrappedShareX = 'wrappedShareX', // Dashboard dashboardKeysLink = 'dashboardKeysLink', dashboardBondLink = 'dashboardBondLink', dashboardRolesLink = 'dashboardRolesLink', dashboardExternalBeaconchaLink = 'dashboardExternalBeaconchaLink', + dashboardExternalBeaconchaEntityLink = 'dashboardExternalBeaconchaEntityLink', dashboardExternalFeesMonitoringLink = 'dashboardExternalFeesMonitoringLink', dashboardExternalOperatorsPortalLink = 'dashboardExternalOperatorsPortalLink', dashboardExternalRatedLink = 'dashboardExternalRatedLink', - dashboardExternalEthSeerLink = 'dashboardExternalEthSeerLink', - // Pages - pageWelcome = 'pageWelcome', - pageStarterPack = 'pageStarterPack', - pageMaintenance = 'pageMaintenance', - pageCreateNodeOperator = 'pageCreateNodeOperator', - pageDashboard = 'pageDashboard', - pageAddKeys = 'pageAddKeys', - pageViewKeys = 'pageViewKeys', - pageRemoveKeys = 'pageRemoveKeys', - pageAddBond = 'pageAddBond', - pageClaimBond = 'pageClaimBond', - pageUnlockBond = 'pageUnlockBond', - pageInboxRequests = 'pageInboxRequests', - pageChangeManagerRole = 'pageAcceptInviteChangeManagerRole', - pageChangeRewardsRole = 'pageChangeRewardsRole', - pageNormalizeQueue = 'pageNormalizeQueue', - page404 = 'page404', - page500 = 'page500', + dashboardExternalMigaLabsLink = 'dashboardExternalMigaLabsLink', + dashboardNotificationSentinelLink = 'dashboardNotificationSentinelLink', // Actions switchNodeOperator = 'switchNodeOperator', + groupSwitchOperator = 'groupSwitchOperator', + // Rewards History + rewardsHistoryExport = 'rewardsHistoryExport', // modifiers - visitWithModeExtended = 'visitWithModeExtended', visitWithReferrer = 'visitWithReferrer', + // Footer + footerTermsOfUse = 'footerTermsOfUse', + footerPrivacyNotice = 'footerPrivacyNotice', + footerFeedbackForm = 'footerFeedbackForm', + footerDiscord = 'footerDiscord', + footerVersion = 'footerVersion', + // ICS + icsPassportLink = 'icsPassportLink', + icsDiscordGuideLink = 'icsDiscordGuideLink', + icsCirclesLink = 'icsCirclesLink', + icsHackmdGuideLink = 'icsHackmdGuideLink', + icsGalxeLink = 'icsGalxeLink', + icsHighSignalLink = 'icsHighSignalLink', + icsYoutubeGuideLink = 'icsYoutubeGuideLink', + icsDiscordChannelLink = 'icsDiscordChannelLink', + icsEtherscanSignaturesLink = 'icsEtherscanSignaturesLink', + icsGithubAddressesLink = 'icsGithubAddressesLink', + // DVT + dvtYoutubeGuideLink = 'dvtYoutubeGuideLink', + dvtDiscordChannelLink = 'dvtDiscordChannelLink', + dvtEtherscanSignaturesLink = 'dvtEtherscanSignaturesLink', + // Exit Keys + exitKeysDappnodeLink = 'exitKeysDappnodeLink', + exitKeysSedgeLink = 'exitKeysSedgeLink', + exitKeysStereumLink = 'exitKeysStereumLink', + exitKeysEthpillarLink = 'exitKeysEthpillarLink', + exitKeysEthdockerLink = 'exitKeysEthdockerLink', + exitKeysSystemdLink = 'exitKeysSystemdLink', + // Bond Info + mevStealingDocsLink = 'mevStealingDocsLink', + lidoRewardsVaultLink = 'lidoRewardsVaultLink', + unbondedValidatorsLink = 'unbondedValidatorsLink', + // Monitoring + monitoringMigalabsLink = 'monitoringMigalabsLink', + monitoringRewardsDocsLink = 'monitoringRewardsDocsLink', + performanceTipsLink = 'performanceTipsLink', + // View Keys + subscribeEventsLink = 'subscribeEventsLink', + operatorPortalDepositsFlowLink = 'operatorPortalDepositsFlowLink', + // Claim + claimWithdrawalsLink = 'claimWithdrawalsLink', + // Other + operatorTypesDocsLink = 'operatorTypesDocsLink', + vanomDashboardLink = 'vanomDashboardLink', + legalPrivacyNoticeLink = 'legalPrivacyNoticeLink', + lidoHomeLink = 'lidoHomeLink', + // Surveys CTA + surveysCtaLink = 'surveysCtaLink', + surveysCtaClose = 'surveysCtaClose', + // Header Actions + clickOperatorTypeButton = 'clickOperatorTypeButton', + clickSwitchOperatorButton = 'clickSwitchOperatorButton', + clickWalletButton = 'clickWalletButton', } export const MATOMO_CLICK_EVENTS: Record< @@ -98,378 +166,490 @@ export const MATOMO_CLICK_EVENTS: Record< MatomoEventType > = { // Welcome - [MATOMO_CLICK_EVENTS_TYPES.connectWallet]: [ - MATOMO_APP_NAME, + [MATOMO_CLICK_EVENTS_TYPES.connectWallet]: createEvent( 'Push «Connect wallet» button', - prefixed`connect_wallet`, - ], - [MATOMO_CLICK_EVENTS_TYPES.connectAsNodeOperator]: [ - MATOMO_APP_NAME, + 'connect_wallet', + ), + [MATOMO_CLICK_EVENTS_TYPES.disconnectWallet]: createEvent( + 'Push «Disconnect» button', + 'disconnect_wallet', + ), + [MATOMO_CLICK_EVENTS_TYPES.clickShowMoreWallets]: createEvent( + 'Push "More wallets" on wallet modal', + 'more_wallets', + ), + [MATOMO_CLICK_EVENTS_TYPES.clickShowLessWallets]: createEvent( + 'Push "Less wallets" on wallet modal', + 'less_wallets', + ), + [MATOMO_CLICK_EVENTS_TYPES.connectAsNodeOperator]: createEvent( 'Push «I am a Node Operator» on Welcome screen', - prefixed`connect_wallet_as_no`, - ], - [MATOMO_CLICK_EVENTS_TYPES.connectToBecomeNodeOperator]: [ - MATOMO_APP_NAME, + 'connect_wallet_as_no', + ), + [MATOMO_CLICK_EVENTS_TYPES.connectToBecomeNodeOperator]: createEvent( 'Push «Become a Node Operator» on Welcome screen', - prefixed`connect_wallet_to_become_no`, - ], - [MATOMO_CLICK_EVENTS_TYPES.welcomeDetailedLink]: [ - MATOMO_APP_NAME, - 'Click on Deailed description about CSM link', - prefixed`welcome_csm_detailed_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.earlyAdoptionLearnMore]: [ - MATOMO_APP_NAME, - 'Click «Learn more about EA» link on Welcome screen', - prefixed`welcome_ea_learn_more_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.earlyAdoptionCuratedList]: [ - MATOMO_APP_NAME, - 'Click «EA curated list» link on Welcome screen', - prefixed`welcome_ea_curated_list`, - ], + 'connect_wallet_to_become_no', + ), + [MATOMO_CLICK_EVENTS_TYPES.welcomeDetailedLink]: createEvent( + 'Click on Detailed description about Module link', + 'welcome_module_detailed_link', + ), // Starter Pack - [MATOMO_CLICK_EVENTS_TYPES.starterPackCreateNodeOperator]: [ - MATOMO_APP_NAME, + [MATOMO_CLICK_EVENTS_TYPES.starterPackCreateNodeOperator]: createEvent( 'Push «Create a Node Operator» on StarterPack screen', - prefixed`starterpack_create_node_operator`, - ], - [MATOMO_CLICK_EVENTS_TYPES.consumedEarlyAdoptionLearnMore]: [ - MATOMO_APP_NAME, - 'Click «Learn more about EA» link on Consumed banner', - prefixed`consumed_ea_lear_more_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.notEligibleEarlyAdoptionLearnMore]: [ - MATOMO_APP_NAME, - 'Click «Learn more about EA» link on NotEligible banner', - prefixed`not_eligible_ea_lear_more_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.partnerDappnode]: [ - MATOMO_APP_NAME, + 'starterpack_create_node_operator', + ), + [MATOMO_CLICK_EVENTS_TYPES.partnerDappnode]: createEvent( 'Click partner «Dappnode» link on StarterPack screen', - prefixed`starterpack_partner_dappnode_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.partnerSedge]: [ - MATOMO_APP_NAME, + 'starterpack_partner_dappnode_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.partnerSedge]: createEvent( 'Click partner «Sedge» link on StarterPack screen', - prefixed`starterpack_partner_sedge_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.partnerStereum]: [ - MATOMO_APP_NAME, + 'starterpack_partner_sedge_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.partnerStereum]: createEvent( 'Click partner «Stereum» link on StarterPack screen', - prefixed`starterpack_partner_stereu_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.partnerEthdocker]: [ - MATOMO_APP_NAME, + 'starterpack_partner_stereum_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.partnerEthdocker]: createEvent( 'Click partner «Eth Docker» link on StarterPack screen', - prefixed`starterpack_partner_ethdocker_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.starterPackCSMLink]: [ - MATOMO_APP_NAME, + 'starterpack_partner_ethdocker_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.starterPackCSMLink]: createEvent( 'Click «About CSM» link on StarterPack screen', - prefixed`starterpack_csm_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.starterPackBondLink]: [ - MATOMO_APP_NAME, - 'Click «Lear about Bond» link on StarterPack screen', - prefixed`starterpack_bond_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.starterPackHadwareLink]: [ - MATOMO_APP_NAME, + 'starterpack_csm_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.starterPackBondLink]: createEvent( + 'Click «Learn about Bond» link on StarterPack screen', + 'starterpack_bond_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.starterPackHardwareLink]: createEvent( 'Click «Run hardware» link on StarterPack screen', - prefixed`starterpack_hardware_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.starterPackSetupValidatorLink]: [ - MATOMO_APP_NAME, + 'starterpack_hardware_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.starterPackSetupValidatorLink]: createEvent( 'Click «Setup validator» link on StarterPack screen', - prefixed`starterpack_setup_validator_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.starterPackGenerateKeysLink]: [ - MATOMO_APP_NAME, + 'starterpack_setup_validator_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.starterPackGenerateKeysLink]: createEvent( 'Click «Generation Keys guide» link on StarterPack screen', - prefixed`starterpack_generate_keys_link`, - ], + 'starterpack_generate_keys_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalJoinPermissionless]: createEvent( + 'Push «Join permissionlessly» button on Operator Type modal', + 'operator_type_modal_join_permissionless', + ), + [MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalApplyIcs]: createEvent( + 'Push «Apply for ICS» button on Operator Type modal', + 'operator_type_modal_apply_ics', + ), + [MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalApplyIdvtc]: createEvent( + 'Push «Apply for IDVTC» button on Operator Type modal', + 'operator_type_modal_apply_idvtc', + ), + [MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalCreateIcs]: createEvent( + 'Push «Create ICS operator» button on Operator Type modal', + 'operator_type_modal_create_ics', + ), + [MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalCreateIdvtc]: createEvent( + 'Push «Create IDVTC operator» button on Operator Type modal', + 'operator_type_modal_create_idvtc', + ), // Forms - [MATOMO_CLICK_EVENTS_TYPES.howBondIsCalculated]: [ - MATOMO_APP_NAME, - 'Click «How bond is calculated» link on Upload form', - prefixed`how_bond_is_calculated_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.depositDataLearnMore]: [ - MATOMO_APP_NAME, + [MATOMO_CLICK_EVENTS_TYPES.depositDataLearnMore]: createEvent( 'Click «Upload Deposit Data learn more» link on Upload form', - prefixed`deposti_data_learn_more_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.howToClaimEth]: [ - MATOMO_APP_NAME, + 'deposit_data_learn_more_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.howToClaimEth]: createEvent( 'Click «Follow FAQ (ETH)» link on Claim form', - prefixed`how_to_claim_eth`, - ], - [MATOMO_CLICK_EVENTS_TYPES.customAddressDescription]: [ - MATOMO_APP_NAME, + 'how_to_claim_eth', + ), + [MATOMO_CLICK_EVENTS_TYPES.customAddressDescription]: createEvent( 'Click «Detailed description of custom addresses» link on Create NO form', - prefixed`cusstom_address_description_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.managerAdressPermissionTypeDescription]: [ - MATOMO_APP_NAME, - 'Click «Detailed description of manager permission type» link on Create NO form', - prefixed`manager_address_permission_type_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.createSuccessKeysTab]: [ - MATOMO_APP_NAME, + 'custom_address_description_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.managerAddressPermissionTypeDescription]: + createEvent( + 'Click «Detailed description of manager permission type» link on Create NO form', + 'manager_address_permission_type_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.createSuccessKeysTab]: createEvent( 'Click «check status on keys tab» link after Create NO', - prefixed`create_success_keys_tab_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.createSuccessBeaconchainDashboard]: [ - MATOMO_APP_NAME, - 'Click «beaconcha.in bashboard» link after Create NO', - prefixed`create_success_beaconchain_dashboard_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.createSuccessBeaconchain]: [ - MATOMO_APP_NAME, + 'create_success_keys_tab_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.createSuccessBeaconchainDashboard]: createEvent( + 'Click «beaconcha.in dashboard» link after Create NO', + 'create_success_beaconchain_dashboard_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.createSuccessBeaconchain]: createEvent( 'Click «beaconcha.in» link after Create NO', - prefixed`create_success_beaconchain_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.createSuccessSubscribeEvents]: [ - MATOMO_APP_NAME, + 'create_success_beaconchain_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.createSuccessSubscribeEvents]: createEvent( 'Click «subscribe events» link after Create NO', - prefixed`create_success_subscribe_events_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.otherModuleLink]: [ - MATOMO_APP_NAME, + 'create_success_subscribe_events_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.otherModuleLink]: createEvent( 'Click «operators.lido.fi» link for other module', - prefixed`operator_in_other_module_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.splitsOrgDocumentation]: [ - MATOMO_APP_NAME, - 'Click «splits.org documentation» link', - prefixed`spilt_org_documentation_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.howToClaimEthSuccessLink]: [ - MATOMO_APP_NAME, + 'operator_in_other_module_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.howToClaimEthSuccessLink]: createEvent( 'Click «How to claim ETH» link in success modal', - prefixed`how_to_claim_eth_success_link`, - ], + 'how_to_claim_eth_success_link', + ), // Common - [MATOMO_CLICK_EVENTS_TYPES.etherscanTxLink]: [ - MATOMO_APP_NAME, + [MATOMO_CLICK_EVENTS_TYPES.etherscanTxLink]: createEvent( 'Click «View on Etherscan» link on TX modal', - prefixed`etherscan_transaction_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.etherscanAddressLink]: [ - MATOMO_APP_NAME, + 'etherscan_transaction_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.etherscanAddressLink]: createEvent( 'Click «View on Etherscan» link on address', - prefixed`etherscan_address_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.beaconchainPubkeyLink]: [ - MATOMO_APP_NAME, + 'etherscan_address_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.beaconchainPubkeyLink]: createEvent( 'Click «View on beaconcha.in» link on pubkey', - prefixed`beaconchain_pubkey_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.feedbackFormLink]: [ - MATOMO_APP_NAME, - 'Click «Submit report with form» link', - prefixed`feedback_form_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.tryCsmOtherNetworkLink]: [ - MATOMO_APP_NAME, - 'Click «Join CSM» in other network link', - prefixed`try_csm_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.stakeShareLimitLinkBanner]: [ - MATOMO_APP_NAME, + 'beaconchain_pubkey_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.migalabsPubkeyLink]: createEvent( + 'Click «View on migalabs.io» link on pubkey', + 'migalabs_pubkey_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.tryOtherNetworkLink]: createEvent( + 'Click «Join» in other network link', + 'try_other_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.stakeShareLimitLinkBanner]: createEvent( 'Click «stake share limit» link on banner', - prefixed`stake_share_limit_link_banner`, - ], + 'stake_share_limit_link_banner', + ), + [MATOMO_CLICK_EVENTS_TYPES.faqItemLink]: createEvent( + 'Click link in FAQ', + 'faq_item_link', + ), // Key status comment - [MATOMO_CLICK_EVENTS_TYPES.howToExitLinkComment]: [ - MATOMO_APP_NAME, + [MATOMO_CLICK_EVENTS_TYPES.howToExitLinkComment]: createEvent( 'Click «Exit key from CL» link on key status comment', - prefixed`exit_key_from_cl_link_comment`, - ], - [MATOMO_CLICK_EVENTS_TYPES.whenValidatorBecomeActiveLinkComment]: [ - MATOMO_APP_NAME, + 'exit_key_from_cl_link_comment', + ), + [MATOMO_CLICK_EVENTS_TYPES.whenValidatorBecomeActiveLinkComment]: createEvent( 'Click «When validator become active» link on key status comment', - prefixed`when_validator_become_active_link_comment`, - ], - [MATOMO_CLICK_EVENTS_TYPES.whenValidatorBecomeWithdrawnLinkComment]: [ - MATOMO_APP_NAME, - 'Click «When validator become withdrawn» link on key status comment', - prefixed`when_validator_become_withdrawn_link_comment`, - ], - [MATOMO_CLICK_EVENTS_TYPES.stakeShareLimitLinkComment]: [ - MATOMO_APP_NAME, + 'when_validator_become_active_link_comment', + ), + [MATOMO_CLICK_EVENTS_TYPES.whenValidatorBecomeWithdrawnLinkComment]: + createEvent( + 'Click «When validator become withdrawn» link on key status comment', + 'when_validator_become_withdrawn_link_comment', + ), + [MATOMO_CLICK_EVENTS_TYPES.stakeShareLimitLinkComment]: createEvent( 'Click «stake share limit» link on key status comment', - prefixed`stake_share_limit_link_comment`, - ], + 'stake_share_limit_link_comment', + ), // Alerts - [MATOMO_CLICK_EVENTS_TYPES.howLearnCsmClose]: [ - MATOMO_APP_NAME, - `Close alert «How did I learn about CSM»`, - prefixed`_close_how_learn_csm`, - ], - [MATOMO_CLICK_EVENTS_TYPES.howToExitLinkRequestToExitAlert]: [ - MATOMO_APP_NAME, + [MATOMO_CLICK_EVENTS_TYPES.howToExitLinkRequestToExitAlert]: createEvent( 'Click «How to exit» link on Request To Exit alert', - prefixed`how_to_exit_link_requset_to_exit_alert`, - ], - [MATOMO_CLICK_EVENTS_TYPES.howToExitLinkStuckKeysAlert]: [ - MATOMO_APP_NAME, - 'Click «How to exit» link on Stuck Keys alert', - prefixed`how_to_exit_link_stuck_keys_alert`, - ], - [MATOMO_CLICK_EVENTS_TYPES.normalizeQueueLinkAlert]: [ - MATOMO_APP_NAME, + 'how_to_exit_link_request_to_exit_alert', + ), + [MATOMO_CLICK_EVENTS_TYPES.normalizeQueueLinkAlert]: createEvent( 'Click «Normalize queue» link on Normalize Queue alert', - prefixed`normalize_queue_link_alert`, - ], - [MATOMO_CLICK_EVENTS_TYPES.unlockBondLinkAlert]: [ - MATOMO_APP_NAME, + 'normalize_queue_link_alert', + ), + [MATOMO_CLICK_EVENTS_TYPES.unlockBondLinkAlert]: createEvent( 'Click «Unlock bond» link on Locked Bond alert', - prefixed`unlock_bond_link_alert`, - ], + 'unlock_bond_link_alert', + ), + [MATOMO_CLICK_EVENTS_TYPES.expiredLockedBondLinkAlert]: createEvent( + 'Click «Unlock bond» link on Expired Locked Bond alert', + 'expired_locked_bond_link_alert', + ), + [MATOMO_CLICK_EVENTS_TYPES.claimIcsLinkAlert]: createEvent( + 'Click «Claim ICS» link on Claim ICS alert', + 'claim_ics_link_alert', + ), + [MATOMO_CLICK_EVENTS_TYPES.claimIdvtcLinkAlert]: createEvent( + 'Click «Claim IDVTC» link on Claim IDVTC alert', + 'claim_idvtc_link_alert', + ), + [MATOMO_CLICK_EVENTS_TYPES.feeRecipientDocsLink]: createEvent( + 'Click «How to change feeRecipient» link on Wrong Fee Recipient alert', + 'fee_recipient_docs_link_alert', + ), + [MATOMO_CLICK_EVENTS_TYPES.feeRecipientDismissButton]: createEvent( + "Click «I've changed the feeRecipient» button on Wrong Fee Recipient alert", + 'fee_recipient_dismiss_button_alert', + ), + [MATOMO_CLICK_EVENTS_TYPES.wrappedAlertClose]: createEvent( + 'Click close button on Wrapped alert', + 'wrapped_alert_close', + ), + [MATOMO_CLICK_EVENTS_TYPES.wrappedAlertLink]: createEvent( + 'Click «See my 2025 wrapped» link on Wrapped alert', + 'wrapped_alert_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.wrappedLetsGo]: createEvent( + "Click «Let's go» button on Wrapped intro", + 'wrapped_lets_go', + ), + [MATOMO_CLICK_EVENTS_TYPES.wrappedRepeat]: createEvent( + 'Click «Repeat» button on Wrapped summary', + 'wrapped_repeat', + ), + [MATOMO_CLICK_EVENTS_TYPES.wrappedShareOpen]: createEvent( + 'Open share modal on Wrapped summary', + 'wrapped_share_open', + ), + [MATOMO_CLICK_EVENTS_TYPES.wrappedShareCopy]: createEvent( + 'Copy image to clipboard in share modal', + 'wrapped_share_copy', + ), + [MATOMO_CLICK_EVENTS_TYPES.wrappedShareNative]: createEvent( + 'Share via native share API in share modal', + 'wrapped_share_native', + ), + [MATOMO_CLICK_EVENTS_TYPES.wrappedShareDownload]: createEvent( + 'Download image in share modal', + 'wrapped_share_download', + ), + [MATOMO_CLICK_EVENTS_TYPES.wrappedShareX]: createEvent( + 'Click «Share on X» button on Wrapped summary', + 'wrapped_share_x', + ), // Dashboard - [MATOMO_CLICK_EVENTS_TYPES.dashboardKeysLink]: [ - MATOMO_APP_NAME, + [MATOMO_CLICK_EVENTS_TYPES.dashboardKeysLink]: createEvent( 'Push «Keys section» arrow on Dashboard screen', - prefixed`dashboard_keys_section`, - ], - [MATOMO_CLICK_EVENTS_TYPES.dashboardBondLink]: [ - MATOMO_APP_NAME, + 'dashboard_keys_section', + ), + [MATOMO_CLICK_EVENTS_TYPES.dashboardBondLink]: createEvent( 'Push «Bond section» arrow on Dashboard screen', - prefixed`dashboard_bond_section`, - ], - [MATOMO_CLICK_EVENTS_TYPES.dashboardRolesLink]: [ - MATOMO_APP_NAME, + 'dashboard_bond_section', + ), + [MATOMO_CLICK_EVENTS_TYPES.dashboardRolesLink]: createEvent( 'Push «Roles section» arrow on Dashboard screen', - prefixed`dashboard_roles_section`, - ], - [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalBeaconchaLink]: [ - MATOMO_APP_NAME, + 'dashboard_roles_section', + ), + [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalBeaconchaLink]: createEvent( 'Click «Beaconcha.in» on Dashboard screen', - prefixed`dashboard_external_beaconcha_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalFeesMonitoringLink]: [ - MATOMO_APP_NAME, + 'dashboard_external_beaconcha_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalBeaconchaEntityLink]: createEvent( + 'Click «Beaconcha.in Entity» on Dashboard screen', + 'dashboard_external_beaconcha_entity_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalFeesMonitoringLink]: createEvent( 'Click «MEV monitoring» on Dashboard screen', - prefixed`dashboard_external_mev_monitoring_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalOperatorsPortalLink]: [ - MATOMO_APP_NAME, + 'dashboard_external_mev_monitoring_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalOperatorsPortalLink]: createEvent( 'Click «Lido operators» on Dashboard screen', - prefixed`dashboard_external_operators_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalRatedLink]: [ - MATOMO_APP_NAME, + 'dashboard_external_operators_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalRatedLink]: createEvent( 'Click «Rated» on Dashboard screen', - prefixed`dashboard_external_rated_link`, - ], - [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalEthSeerLink]: [ - MATOMO_APP_NAME, - 'Click «EthSeer» on Dashboard screen', - prefixed`dashboard_external_ethseer_link`, - ], - // Pages - [MATOMO_CLICK_EVENTS_TYPES.pageWelcome]: [ - MATOMO_APP_NAME, - 'View page «Welcome»', - prefixed`view_welcome_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageStarterPack]: [ - MATOMO_APP_NAME, - 'View page «StarterPack»', - prefixed`view_starter_pack_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageMaintenance]: [ - MATOMO_APP_NAME, - 'View page «Maintenance»', - prefixed`view_maintenance_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageCreateNodeOperator]: [ - MATOMO_APP_NAME, - 'View page «CreateNodeOperator»', - prefixed`view_create_node_operator_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageDashboard]: [ - MATOMO_APP_NAME, - 'View page «Dashboard»', - prefixed`view_dashboard_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageAddKeys]: [ - MATOMO_APP_NAME, - 'View page «AddKeys»', - prefixed`view_add_keys_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageViewKeys]: [ - MATOMO_APP_NAME, - 'View page «ViewKeys»', - prefixed`view_view_keys_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageRemoveKeys]: [ - MATOMO_APP_NAME, - 'View page «RemoveKeys»', - prefixed`view_remove_keys_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageAddBond]: [ - MATOMO_APP_NAME, - 'View page «AddBond»', - prefixed`view_add_bond_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageClaimBond]: [ - MATOMO_APP_NAME, - 'View page «ClaimBond»', - prefixed`view_claim_bond_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageUnlockBond]: [ - MATOMO_APP_NAME, - 'View page «UnlockBond»', - prefixed`view_unlock_bond_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageInboxRequests]: [ - MATOMO_APP_NAME, - 'View page «InboxRequests»', - prefixed`view_inbox_requests_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageChangeManagerRole]: [ - MATOMO_APP_NAME, - 'View page «ChangeManagerRole»', - prefixed`view_change_manager_role_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageChangeRewardsRole]: [ - MATOMO_APP_NAME, - 'View page «ChangeRewardsRole»', - prefixed`view_change_rewards_role_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.pageNormalizeQueue]: [ - MATOMO_APP_NAME, - 'View page «NormalizeQueue»', - prefixed`view_normalize_queue_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.page404]: [ - MATOMO_APP_NAME, - 'View page «404»', - prefixed`view_404_page`, - ], - [MATOMO_CLICK_EVENTS_TYPES.page500]: [ - MATOMO_APP_NAME, - 'View page «500»', - prefixed`view_500_page`, - ], + 'dashboard_external_rated_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.dashboardExternalMigaLabsLink]: createEvent( + 'Click «MigaLabs» on Dashboard screen', + 'dashboard_external_migalabs_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.dashboardNotificationSentinelLink]: createEvent( + 'Click «Notification Sentinel» on Dashboard screen', + 'dashboard_notification_sentinel_link', + ), // Actions - [MATOMO_CLICK_EVENTS_TYPES.switchNodeOperator]: [ - MATOMO_APP_NAME, + [MATOMO_CLICK_EVENTS_TYPES.switchNodeOperator]: createEvent( 'Switch Node Operator', - prefixed`switch_node_operator`, - ], + 'switch_node_operator', + ), + [MATOMO_CLICK_EVENTS_TYPES.groupSwitchOperator]: createEvent( + 'Click «Switch to this operator» on Group page', + 'group_switch_operator', + ), + // Rewards History + [MATOMO_CLICK_EVENTS_TYPES.rewardsHistoryExport]: createEvent( + 'Push «Export all to CSV» button on Rewards History page', + 'rewards_history_export', + ), // Modifiers - [MATOMO_CLICK_EVENTS_TYPES.visitWithModeExtended]: [ - MATOMO_APP_NAME, - 'Visit with mode extended', - prefixed`visit_mode_extended`, - ], - [MATOMO_CLICK_EVENTS_TYPES.visitWithReferrer]: [ - MATOMO_APP_NAME, + [MATOMO_CLICK_EVENTS_TYPES.visitWithReferrer]: createEvent( 'Visite with referrer', - prefixed`visit_referrer`, - ], + 'visit_referrer', + ), + // Footer + [MATOMO_CLICK_EVENTS_TYPES.footerTermsOfUse]: createEvent( + 'Click «Terms of Use» link in footer', + 'footer_terms_of_use_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.footerPrivacyNotice]: createEvent( + 'Click «Privacy Notice» link in footer', + 'footer_privacy_notice_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.footerFeedbackForm]: createEvent( + 'Click «Feedback form» link in footer', + 'footer_feedback_form_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.footerDiscord]: createEvent( + 'Click «Discord» link in footer', + 'footer_discord_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.footerVersion]: createEvent( + 'Click version link in footer', + 'footer_version_link', + ), + // ICS + [MATOMO_CLICK_EVENTS_TYPES.icsPassportLink]: createEvent( + 'Click «Human Passport» link on ICS page', + 'ics_passport_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.icsDiscordGuideLink]: createEvent( + 'Click Discord guide link on ICS page', + 'ics_discord_guide_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.icsCirclesLink]: createEvent( + 'Click «Circles» link on ICS page', + 'ics_circles_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.icsHackmdGuideLink]: createEvent( + 'Click HackMD guide link on ICS page', + 'ics_hackmd_guide_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.icsGalxeLink]: createEvent( + 'Click «Galxe» link on ICS page', + 'ics_galxe_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.icsHighSignalLink]: createEvent( + 'Click «High Signal» link on ICS page', + 'ics_high_signal_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.icsYoutubeGuideLink]: createEvent( + 'Click YouTube guide link on ICS page', + 'ics_youtube_guide_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.icsDiscordChannelLink]: createEvent( + 'Click Discord CSM channel link on ICS page', + 'ics_discord_channel_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.icsEtherscanSignaturesLink]: createEvent( + 'Click Etherscan verified signatures link on ICS page', + 'ics_etherscan_signatures_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.icsGithubAddressesLink]: createEvent( + 'Click GitHub ICS addresses link on ICS page', + 'ics_github_addresses_link', + ), + // DVT + [MATOMO_CLICK_EVENTS_TYPES.dvtYoutubeGuideLink]: createEvent( + 'Click YouTube guide link on DVT page', + 'dvt_youtube_guide_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.dvtDiscordChannelLink]: createEvent( + 'Click Discord CSM channel link on DVT page', + 'dvt_discord_channel_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.dvtEtherscanSignaturesLink]: createEvent( + 'Click Etherscan verified signatures link on DVT page', + 'dvt_etherscan_signatures_link', + ), + // Exit Keys + [MATOMO_CLICK_EVENTS_TYPES.exitKeysDappnodeLink]: createEvent( + 'Click «Dappnode» exit guide link', + 'exit_keys_dappnode_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.exitKeysSedgeLink]: createEvent( + 'Click «Sedge» exit guide link', + 'exit_keys_sedge_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.exitKeysStereumLink]: createEvent( + 'Click «Stereum» exit guide link', + 'exit_keys_stereum_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.exitKeysEthpillarLink]: createEvent( + 'Click «ETH Pillar» exit guide link', + 'exit_keys_ethpillar_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.exitKeysEthdockerLink]: createEvent( + 'Click «ETH Docker» exit guide link', + 'exit_keys_ethdocker_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.exitKeysSystemdLink]: createEvent( + 'Click «Systemd» exit guide link', + 'exit_keys_systemd_link', + ), + // Bond Info + [MATOMO_CLICK_EVENTS_TYPES.mevStealingDocsLink]: createEvent( + 'Click «MEV stealing» docs link', + 'mev_stealing_docs_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.lidoRewardsVaultLink]: createEvent( + 'Click «Lido rewards vault» link', + 'lido_rewards_vault_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.unbondedValidatorsLink]: createEvent( + 'Click «Unbonded validators» docs link', + 'unbonded_validators_link', + ), + // Monitoring + [MATOMO_CLICK_EVENTS_TYPES.monitoringMigalabsLink]: createEvent( + 'Click «MigaLabs» link on Monitoring page', + 'monitoring_migalabs_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.monitoringRewardsDocsLink]: createEvent( + 'Click «Rewards» docs link on Monitoring page', + 'monitoring_rewards_docs_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.performanceTipsLink]: createEvent( + 'Click «Performance tips» link', + 'performance_tips_link', + ), + // View Keys + [MATOMO_CLICK_EVENTS_TYPES.subscribeEventsLink]: createEvent( + 'Click «Subscribe events» link on View Keys page', + 'subscribe_events_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.operatorPortalDepositsFlowLink]: createEvent( + 'Click «Deposits flow» link on View Keys page', + 'operator_portal_deposits_flow_link', + ), + // Claim + [MATOMO_CLICK_EVENTS_TYPES.claimWithdrawalsLink]: createEvent( + 'Click «Claim withdrawals» link on Claim page', + 'claim_withdrawals_link', + ), + // Other + [MATOMO_CLICK_EVENTS_TYPES.operatorTypesDocsLink]: createEvent( + 'Click «Operator types» docs link', + 'operator_types_docs_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.vanomDashboardLink]: createEvent( + 'Click «VaNOM dashboard» link', + 'vanom_dashboard_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.legalPrivacyNoticeLink]: createEvent( + 'Click «Privacy Notice» link in legal disclaimer', + 'legal_privacy_notice_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.lidoHomeLink]: createEvent( + 'Click Lido logo link', + 'lido_home_link', + ), + // Surveys CTA + [MATOMO_CLICK_EVENTS_TYPES.surveysCtaLink]: createEvent( + 'Click «Surveys» link on Surveys CTA banner', + 'surveys_cta_link', + ), + [MATOMO_CLICK_EVENTS_TYPES.surveysCtaClose]: createEvent( + 'Close Surveys CTA banner', + 'surveys_cta_close', + ), + // Header Actions + [MATOMO_CLICK_EVENTS_TYPES.clickOperatorTypeButton]: createEvent( + 'Click operator type button in header', + 'click_operator_type_button', + ), + [MATOMO_CLICK_EVENTS_TYPES.clickSwitchOperatorButton]: createEvent( + 'Click switch operator button in header', + 'click_switch_operator_button', + ), + [MATOMO_CLICK_EVENTS_TYPES.clickWalletButton]: createEvent( + 'Click wallet button in header', + 'click_wallet_button', + ), }; diff --git a/consts/matomo-wallets-events.ts b/consts/matomo-wallets-events.ts index 77b194d97..586cf1fee 100644 --- a/consts/matomo-wallets-events.ts +++ b/consts/matomo-wallets-events.ts @@ -1,403 +1,59 @@ -import { MatomoEventType, trackEvent } from '@lidofinance/analytics-matomo'; -import { Metrics as WalletsMetrics } from 'reef-knot/connect-wallet-modal'; -import { MATOMO_APP_NAME, prefixed } from './matomo-click-events'; +import { trackEvent } from '@lidofinance/analytics-matomo'; +import type { ReefKnotWalletsModalConfig } from 'reef-knot/types'; +import type { WalletIdsEthereum } from 'reef-knot/wallets'; +import { createEvent, MATOMO_CLICK_EVENTS } from './matomo-click-events'; -export const enum MATOMO_WALLETS_EVENTS_TYPES { - onClickAmbire = 'onClickAmbire', - onConnectAmbire = 'onConnectAmbire', - onClickBlockchaincom = 'onClickBlockchaincom', - onConnectBlockchaincom = 'onConnectBlockchaincom', - onClickBrave = 'onClickBrave', - onConnectBrave = 'onConnectBrave', - onClickCoin98 = 'onClickCoin98', - onConnectCoin98 = 'onConnectCoin98', - onClickCoinbase = 'onClickCoinbase', - onConnectCoinbase = 'onConnectCoinbase', - onClickExodus = 'onClickExodus', - onConnectExodus = 'onConnectExodus', - onClickGamestop = 'onClickGamestop', - onConnectGamestop = 'onConnectGamestop', - onClickImToken = 'onClickImToken', - onConnectImToken = 'onConnectImToken', - onClickLedger = 'onClickLedger', - onConnectLedger = 'onConnectLedger', - onClickMathWallet = 'onClickMathWallet', - onConnectMathWallet = 'onConnectMathWallet', - onClickMetamask = 'onClickMetamask', - onConnectMetamask = 'onConnectMetamask', - onClickOperaWallet = 'onClickOperaWallet', - onConnectOperaWallet = 'onConnectOperaWallet', - onClickTally = 'onClickTally', - onConnectTally = 'onConnectTally', - onClickTrust = 'onClickTrust', - onConnectTrust = 'onConnectTrust', - onClickWC = 'onClickWC', - onConnectWC = 'onConnectWC', - onClickXdefi = 'onClickXdefi', - onConnectXdefi = 'onConnectXdefi', - onClickZenGo = 'onClickZenGo', - onConnectZenGo = 'onConnectZenGo', - onClickZerion = 'onClickZerion', - onConnectZerion = 'onConnectZerion', - onClickOkx = 'onClickOkx', - onConnectOkx = 'onConnectOkx', - onClickPhantom = 'onClickPhantom', - onConnectPhantom = 'onConnectPhantom', - onClickBitkeep = 'onClickBitkeep', - onConnectBitkeep = 'onConnectBitkeep', -} +type MetricProps = Pick< + ReefKnotWalletsModalConfig, + | 'onClickTermsAccept' + | 'onClickWalletsMore' + | 'onClickWalletsLess' + | 'onConnectStart' + | 'onConnectSuccess' +>; -export const MATOMO_WALLETS_EVENTS: Record< - MATOMO_WALLETS_EVENTS_TYPES, - MatomoEventType -> = { - [MATOMO_WALLETS_EVENTS_TYPES.onClickAmbire]: [ - MATOMO_APP_NAME, - 'Click on Ambire wallet', - prefixed`click_ambire`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectAmbire]: [ - MATOMO_APP_NAME, - 'Connect Ambire wallet', - prefixed`connect_ambire`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickBlockchaincom]: [ - MATOMO_APP_NAME, - 'Click Blockchain.com wallet', - prefixed`click_blockchaincom`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectBlockchaincom]: [ - MATOMO_APP_NAME, - 'Connect Blockchain.com wallet', - prefixed`connect_blockchaincom`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickBrave]: [ - MATOMO_APP_NAME, - 'Click Brave wallet', - prefixed`click_brave`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectBrave]: [ - MATOMO_APP_NAME, - 'Connect Brave wallet', - prefixed`connect_brave`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickCoin98]: [ - MATOMO_APP_NAME, - 'Click Coin98 wallet', - prefixed`click_coin98`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectCoin98]: [ - MATOMO_APP_NAME, - 'Connect Coin98 wallet', - prefixed`connect_coin98`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickCoinbase]: [ - MATOMO_APP_NAME, - 'Click Coinbase Wallet wallet', - prefixed`click_coinbase_wallet`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectCoinbase]: [ - MATOMO_APP_NAME, - 'Connect Coinbase Wallet wallet', - prefixed`connect_coinbase_wallet`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickExodus]: [ - MATOMO_APP_NAME, - 'Click Exodus wallet', - prefixed`click_exodus`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectExodus]: [ - MATOMO_APP_NAME, - 'Connect Exodus wallet', - prefixed`connect_exodus`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickGamestop]: [ - MATOMO_APP_NAME, - 'Click Gamestop wallet', - prefixed`click_gamestop`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectGamestop]: [ - MATOMO_APP_NAME, - 'Connect Gamestop wallet', - prefixed`connect_gamestop`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickImToken]: [ - MATOMO_APP_NAME, - 'Click imToken wallet', - prefixed`click_imtoken`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectImToken]: [ - MATOMO_APP_NAME, - 'Connect imToken wallet', - prefixed`connect_imtoken`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickLedger]: [ - MATOMO_APP_NAME, - 'Click Ledger wallet', - prefixed`click_ledger`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectLedger]: [ - MATOMO_APP_NAME, - 'Connect Ledger wallet', - prefixed`connect_ledger`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickMathWallet]: [ - MATOMO_APP_NAME, - 'Click MathWallet wallet', - prefixed`click_mathwallet`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectMathWallet]: [ - MATOMO_APP_NAME, - 'Connect MathWallet wallet', - prefixed`connect_mathwallet`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickMetamask]: [ - MATOMO_APP_NAME, - 'Click Metamask wallet', - prefixed`click_metamask`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectMetamask]: [ - MATOMO_APP_NAME, - 'Connect Metamask wallet', - prefixed`connect_metamask`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickOperaWallet]: [ - MATOMO_APP_NAME, - 'Click Opera wallet', - prefixed`click_opera`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectOperaWallet]: [ - MATOMO_APP_NAME, - 'Connect Opera wallet', - prefixed`connect_opera`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickTally]: [ - MATOMO_APP_NAME, - 'Click Tally wallet', - prefixed`click_tally`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectTally]: [ - MATOMO_APP_NAME, - 'Connect Tally wallet', - prefixed`connect_tally`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickTrust]: [ - MATOMO_APP_NAME, - 'Click Trust wallet', - prefixed`click_trust`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectTrust]: [ - MATOMO_APP_NAME, - 'Connect Trust wallet', - prefixed`connect_trust`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickWC]: [ - MATOMO_APP_NAME, - 'Click WalletConnect wallet', - prefixed`click_walletconnect`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectWC]: [ - MATOMO_APP_NAME, - 'Connect WalletConnect wallet', - prefixed`connect_walletconnect`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickXdefi]: [ - MATOMO_APP_NAME, - 'Click XDEFI wallet', - prefixed`click_xdefi`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectXdefi]: [ - MATOMO_APP_NAME, - 'Connect XDEFI wallet', - prefixed`connect_xdefi`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickZenGo]: [ - MATOMO_APP_NAME, - 'Click ZenGo wallet', - prefixed`click_zengo`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectZenGo]: [ - MATOMO_APP_NAME, - 'Connect ZenGo wallet', - prefixed`connect_zengo`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickZerion]: [ - MATOMO_APP_NAME, - 'Click Zerion wallet', - prefixed`click_zerion`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectZerion]: [ - MATOMO_APP_NAME, - 'Connect Zerion wallet', - prefixed`connect_zerion`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickOkx]: [ - MATOMO_APP_NAME, - 'Click OKX wallet', - prefixed`click_okx`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectOkx]: [ - MATOMO_APP_NAME, - 'Connect OKX wallet', - prefixed`connect_okx`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickPhantom]: [ - MATOMO_APP_NAME, - 'Click Phantom wallet', - prefixed`click_phantom`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectPhantom]: [ - MATOMO_APP_NAME, - 'Connect Phantom wallet', - prefixed`connect_phantom`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickBitkeep]: [ - MATOMO_APP_NAME, - 'Click BitKeep wallet', - prefixed`click_bitkeep`, - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectBitkeep]: [ - MATOMO_APP_NAME, - 'Connect BitKeep wallet', - prefixed`connect_bitkeep`, - ], +type EventsData = Partial>; + +const EVENTS_DATA_CONNECT_START: EventsData = { + ambire: ['on Ambire', 'ambire'], + bitget: ['BitGet', 'bitget'], + browserExtension: ['Browser', 'browser'], + coinbaseSmartWallet: ['Coinbase Smart Wallet', 'coinbase_smart_wallet'], + imToken: ['imToken', 'imtoken'], + ledgerHID: ['Ledger', 'ledger'], + metaMask: ['Metamask', 'metamask'], + okx: ['OKX', 'okx'], + walletConnect: ['WalletConnect', 'walletconnect'], + anchorageDigital: ['Anchorage Digital', 'anchorage_digital'], +} as const; + +const EVENTS_DATA_CONNECT_SUCCESS: EventsData = { + ...EVENTS_DATA_CONNECT_START, + ambire: ['Ambire', 'ambire'], }; -export const walletsMetrics: WalletsMetrics = { - events: { - click: { - handlers: { - onClickAmbire: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickAmbire); - }, - onClickBlockchaincom: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickBlockchaincom); - }, - onClickBrave: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickBrave); - }, - onClickCoin98: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickCoin98); - }, - onClickCoinbase: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickCoinbase); - }, - onClickExodus: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickExodus); - }, - onClickGamestop: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickGamestop); - }, - onClickImToken: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickImToken); - }, - onClickLedger: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickLedger); - }, - onClickMathWallet: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickMathWallet); - }, - onClickMetamask: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickMetamask); - }, - onClickOperaWallet: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickOperaWallet); - }, - onClickTally: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickTally); - }, - onClickTrust: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickTrust); - }, - onClickWalletconnect: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickWC); - }, - onClickXdefi: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickXdefi); - }, - onClickZenGo: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickZenGo); - }, - onClickZerion: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickZerion); - }, - onClickOkx: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickOkx); - }, - onClickPhantom: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickPhantom); - }, - onClickBitkeep: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickBitkeep); - }, - }, - }, - connect: { - handlers: { - onConnectAmbire: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectAmbire); - }, - onConnectBlockchaincom: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectBlockchaincom); - }, - onConnectBrave: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectBrave); - }, - onConnectCoin98: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectCoin98); - }, - onConnectCoinbase: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectCoinbase); - }, - onConnectExodus: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectExodus); - }, - onConnectGamestop: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectGamestop); - }, - onConnectImToken: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectImToken); - }, - onConnectLedger: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectLedger); - }, - onConnectMathWallet: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectMathWallet); - }, - onConnectMetamask: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectMetamask); - }, - onConnectOperaWallet: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectOperaWallet); - }, - onConnectTally: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectTally); - }, - onConnectTrust: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectTrust); - }, - onConnectWalletconnect: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectWC); - }, - onConnectXdefi: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectXdefi); - }, - onConnectZenGo: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectZenGo); - }, - onConnectZerion: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectZerion); - }, - onConnectOkx: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectOkx); - }, - onConnectPhantom: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectPhantom); - }, - onConnectBitkeep: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectBitkeep); - }, - }, - }, +export const walletMetricProps: MetricProps = { + onClickWalletsLess: () => + trackEvent(...MATOMO_CLICK_EVENTS.clickShowLessWallets), + + onClickWalletsMore: () => + trackEvent(...MATOMO_CLICK_EVENTS.clickShowMoreWallets), + + onConnectStart: ({ walletId }) => { + const eventData = EVENTS_DATA_CONNECT_START[walletId]; + if (eventData) { + trackEvent( + ...createEvent(`Click ${eventData[0]} wallet`, `click_${eventData[1]}`), + ); + } + }, + + onConnectSuccess: ({ walletId }) => { + const eventData = EVENTS_DATA_CONNECT_SUCCESS[walletId]; + if (eventData) { + trackEvent( + ...createEvent(`Connect ${eventData[0]}`, `connect_${eventData[1]}`), + ); + } }, }; diff --git a/consts/metrics.ts b/consts/metrics.ts index 353a810d1..e6f8140c6 100644 --- a/consts/metrics.ts +++ b/consts/metrics.ts @@ -5,6 +5,6 @@ export const METRICS_PREFIX = 'csm_widget_ui_'; export const enum METRIC_NAMES { REQUESTS_TOTAL = 'requests_total', API_RESPONSE = 'api_response', - SUBGRAPHS_RESPONSE = 'subgraphs_response', ETH_CALL_ADDRESS_TO = 'eth_call_address_to', + VALIDATION_FILE_LOAD_ERROR = 'validation_file_load_error', } diff --git a/consts/module.ts b/consts/module.ts new file mode 100644 index 000000000..51a06d09a --- /dev/null +++ b/consts/module.ts @@ -0,0 +1,28 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { config } from 'config'; + +export const MODULE_METADATA = { + [MODULE_NAME.CSM]: { + title: 'Community Staking Module', + shortTitle: 'CSM', + shortName: 'CSM', + description: + 'The Community Staking Module is a permissionless staking module aimed at attracting community stakers to participate in the Lido on Ethereum protocol as Node Operators', + host: 'https://csm.lido.fi', + previewFile: 'csm-preview.png', + }, + [MODULE_NAME.CM]: { + title: 'Curated Module', + shortTitle: 'CM v2', + shortName: 'CM', + description: + 'The Curated Module v2 consists of allow-listed independent professional staking organizations and Ethereum client teams, which operate validators using the protocol', + host: 'https://cm.testnet.fi', // TODO: replace to lido.fi when CM will be released + previewFile: 'cm-preview.png', + }, +} as const; + +export const moduleMeta = MODULE_METADATA[config.module]; + +export const isModuleCSM = config.module === MODULE_NAME.CSM; +export const isModuleCM = config.module === MODULE_NAME.CM; diff --git a/consts/operator-type-metadata.ts b/consts/operator-type-metadata.ts new file mode 100644 index 000000000..d622a6547 --- /dev/null +++ b/consts/operator-type-metadata.ts @@ -0,0 +1,129 @@ +import { + getOperatorTypeByCurveId, + MODULE_NAME, + OPERATOR_TYPE, + SUPPORTED_CHAINS, +} from '@lidofinance/lido-csm-sdk'; + +// UI-only classification for curve ids not owned by any gate; the SDK enum +// contains real operator types only. +export const CUSTOM_CURVE = 'CC' as const; +export type DisplayOperatorType = OPERATOR_TYPE | typeof CUSTOM_CURVE; + +export type OperatorTypeMetadata = { + name: string; + short: string; + title: string; + description: string; +}; + +export const OPERATOR_TYPE_METADATA: Record< + DisplayOperatorType, + OperatorTypeMetadata +> = { + [OPERATOR_TYPE.CSM_DEF]: { + name: 'Default', + short: 'DEF', + title: 'Default (DEF)', + description: + 'The simplest way to start validating in CSM. Upload keys under the general parameters without any permission or verification. At any point in the future, you may apply to become an Identified Community Staker to access more favorable parameters.', + }, + [OPERATOR_TYPE.CSM_LEA]: { + name: 'Legacy Early Adopter', + short: 'LEA', + title: 'Legacy Early Adopter (LEA)', + description: + 'Legacy early adopter operator type recognizing early participants in the Community Staking Module', + }, + [OPERATOR_TYPE.CSM_ICS]: { + name: 'Identified Community Staker', + short: 'ICS', + title: 'Identified Community Staker (ICS)', + description: + 'Obtain enhanced validation parameters by becoming recognized as an independent Community Staker. Please note that the verification process takes time and requires the submission of specific supporting proofs.', + }, + [OPERATOR_TYPE.CSM_IDVTC]: { + name: 'Identified DVT Cluster', + short: 'IDVTC', + title: 'Identified DVT Cluster (IDVTC)', + description: + 'Unlock a more resilient and capital-efficient validation path by creating a verified DVT cluster of independent Community Stakers. Approval requires meeting criteria and completing verification.', + }, + [OPERATOR_TYPE.CM_PTO]: { + name: 'Professional Trusted Operator', + short: 'PTO', + title: 'Professional Trusted Operator (PTO)', + description: + 'This type represents professional operators with a proven track record of strong performance, operational reliability, and ongoing adherence to the Lido protocol standards', + }, + [OPERATOR_TYPE.CM_PO]: { + name: 'Professional Operator', + short: 'PO', + title: 'Professional Operator (PO)', + description: + 'This type serves as an initial stage in the validation journey of professional staking organizations, entering the Lido protocol validation as part of the Curated Module v2', + }, + [OPERATOR_TYPE.CM_PGO]: { + name: 'Public Good Operator', + short: 'PGO', + title: 'Public Good Operator (PGO)', + description: + 'This type acknowledges entities that strengthen the Ethereum ecosystem through client development, their financial support, or contributing to the broader public infrastructure', + }, + [OPERATOR_TYPE.CM_DO]: { + name: 'Decentralization Operator', + short: 'DO', + title: 'Decentralization Operator (DO)', + description: + 'This type recognizes entities that advance Ethereum decentralization by operating nodes in underrepresented regions or running unique client and infrastructure combinations', + }, + [OPERATOR_TYPE.CM_EEO]: { + name: 'Extra Effort Operator', + short: 'EEO', + title: 'Extra Effort Operator (EEO)', + description: + 'This type is for entities that demonstrate strong alignment with the Lido protocol through impactful contributions, such as governance participation and stVaults adoption', + }, + [OPERATOR_TYPE.CM_IODC]: { + name: 'Intra-Operator DVT Cluster', + short: 'IODC', + title: 'Intra-Operator DVT Cluster (IODC)', + description: + 'This type is designed for distributed validator clusters operated by a single entity, leveraging DVT to enhance validator security, redundancy, and operational reliability', + }, + [OPERATOR_TYPE.CM_IODCP]: { + name: 'Intra-Operator DVT Cluster Plus', + short: 'IODC+', + title: 'Intra-Operator DVT Cluster Plus (IODC+)', + description: + 'This type is designed for distributed validator clusters operated by a single entity, leveraging DVT to enhance validator security, redundancy, and operational reliability', + }, + [CUSTOM_CURVE]: { + name: 'Custom Curve', + short: 'CC', + title: 'Custom Curve (CC)', + description: 'Custom Curve', + }, +}; + +// Classify a curve id for display: gate-owned curves resolve to their +// operator type, any other defined curve id is a Custom Curve. +export const getDisplayOperatorType = ( + chainId: SUPPORTED_CHAINS, + moduleName: MODULE_NAME, + curveId: bigint | undefined, +): DisplayOperatorType | undefined => { + if (curveId === undefined) return undefined; + return getOperatorTypeByCurveId(chainId, moduleName, curveId) ?? CUSTOM_CURVE; +}; + +// For components prefer the hooks from shared/hooks (useCurveMetadata et al.); +// this pure variant is for non-reactive contexts like tx-stage callbacks. +export const getCurveMetadata = ( + chainId: SUPPORTED_CHAINS, + moduleName: MODULE_NAME, + curveId: bigint | undefined, +) => { + const operatorType = getDisplayOperatorType(chainId, moduleName, curveId); + return operatorType ? OPERATOR_TYPE_METADATA[operatorType] : undefined; +}; diff --git a/consts/react-query-strategies.ts b/consts/react-query-strategies.ts new file mode 100644 index 000000000..94a4d9ee1 --- /dev/null +++ b/consts/react-query-strategies.ts @@ -0,0 +1,25 @@ +export const STRATEGY_IMMUTABLE = { + staleTime: Infinity, + refetchOnWindowFocus: false, + refetchOnReconnect: false, +}; + +export const STRATEGY_CONSTANT = { + staleTime: Infinity, + refetchOnWindowFocus: false, + refetchOnReconnect: false, + refetchInterval: 10 * 60 * 1000, // 10 minutes +}; + +export const STRATEGY_LAZY = { + staleTime: 5 * 60 * 1000, // 5 minutes + refetchOnWindowFocus: false, + refetchOnReconnect: true, +}; + +export const STRATEGY_EAGER = { + staleTime: 3000, // 3 seconds + refetchOnWindowFocus: true, + refetchOnReconnect: true, + refetchInterval: 10000, // 10 seconds +}; diff --git a/consts/roles.ts b/consts/roles.ts index 473059808..4f0b3fa97 100644 --- a/consts/roles.ts +++ b/consts/roles.ts @@ -1,16 +1,20 @@ -export const ROLES = { - MANAGER: 'MANAGER', - REWARDS: 'REWARDS', -} as const; +import { ROLES } from '@lidofinance/lido-csm-sdk'; -export type ROLES = keyof typeof ROLES; +export const ROLES_METADATA = { + [ROLES.REWARDS]: { + short: 'R', + title: 'rewards', + capitalizedTitle: 'Rewards', + }, + [ROLES.MANAGER]: { + short: 'M', + title: 'manager', + capitalizedTitle: 'Manager', + }, +}; -// TODO: spectacular -export const ROLE_CODE = { - NONE: 0, - REWARDS: 1, - MANAGER: 2, - REWARDS_AND_MANAGER: 3, -} as const; - -export type ROLE_CODE = (typeof ROLE_CODE)[keyof typeof ROLE_CODE]; +export const getRoleTitle = (role: ROLES, capitalized = false) => { + return capitalized + ? ROLES_METADATA[role].capitalizedTitle + : ROLES_METADATA[role].title; +}; diff --git a/consts/swr-strategies.ts b/consts/swr-strategies.ts deleted file mode 100644 index 13af19fba..000000000 --- a/consts/swr-strategies.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { SWRConfiguration } from 'swr'; - -const MINUTE_MS = 1000 * 60; - -type StrategyConfig = Pick< - SWRConfiguration, - | 'revalidateIfStale' - | 'revalidateOnFocus' - | 'revalidateOnReconnect' - | 'refreshInterval' - | 'focusThrottleInterval' - | 'dedupingInterval' ->; - -export const STRATEGY_IMMUTABLE: StrategyConfig = { - revalidateIfStale: false, - revalidateOnFocus: false, - revalidateOnReconnect: false, -}; - -export const STRATEGY_CONSTANT: StrategyConfig = { - revalidateIfStale: false, - revalidateOnFocus: false, - revalidateOnReconnect: false, - refreshInterval: 10 * MINUTE_MS, -}; - -export const STRATEGY_LAZY: StrategyConfig = { - revalidateOnFocus: false, - revalidateIfStale: true, - revalidateOnReconnect: true, - refreshInterval: 5 * MINUTE_MS, -}; - -export const STRATEGY_EAGER: StrategyConfig = { - revalidateOnFocus: true, - revalidateIfStale: true, - revalidateOnReconnect: true, - focusThrottleInterval: 10000, - dedupingInterval: 3000, -}; diff --git a/consts/text.ts b/consts/text.ts index bd337afcf..a82b60f93 100644 --- a/consts/text.ts +++ b/consts/text.ts @@ -2,3 +2,5 @@ export const DATA_UNAVAILABLE = 'N/A'; export const BOND_INSUFFICIENT = 'Insufficient bond'; export const BOND_EXCESS = 'Excess bond'; + +export const INSTANT_WAITING_TIME = '~ 1 min'; diff --git a/consts/tokens.ts b/consts/tokens.ts index 9feb17d8a..c9017ef9e 100644 --- a/consts/tokens.ts +++ b/consts/tokens.ts @@ -1,13 +1,4 @@ -import { parseEther } from '@ethersproject/units'; -import { TOKENS as TOKENS_SDK } from '@lido-sdk/constants'; - -export const TOKENS = { - ETH: 'ETH', - [TOKENS_SDK.STETH]: TOKENS_SDK.STETH, - [TOKENS_SDK.WSTETH]: TOKENS_SDK.WSTETH, -} as const; - -export type TOKENS = keyof typeof TOKENS; +import { parseEther } from 'viem'; // one eth export const ONE_ETH = parseEther('1'); @@ -16,4 +7,6 @@ export const ONE_ETH = parseEther('1'); export const MAX_ETH_AMOUNT = parseEther('1000'); // min 100 wei to claim (unstETH); -export const MIN_ETH_AMOUNT = 100; +export const MIN_ETH_AMOUNT = 100n; + +export const HIGH_EJECTION_COST_THRESHOLD = parseEther('0.01'); diff --git a/consts/treshhold.ts b/consts/treshhold.ts deleted file mode 100644 index c03b19b5c..000000000 --- a/consts/treshhold.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Rounding threshold for stETH token - * - * 10 wei - */ -export const ROUNDING_THRESHOLD = 10; diff --git a/consts/tx.ts b/consts/tx.ts deleted file mode 100644 index 246f69f8b..000000000 --- a/consts/tx.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { BigNumber } from 'ethers'; - -// TODO: review - -export const WSTETH_APPROVE_GAS_LIMIT = BigNumber.from(78000); - -export const WRAP_FROM_ETH_GAS_LIMIT = BigNumber.from(100000); -export const WRAP_GAS_LIMIT = BigNumber.from(140000); -export const WRAP_GAS_LIMIT_GOERLI = BigNumber.from(120000); -export const UNWRAP_GAS_LIMIT = BigNumber.from(115000); diff --git a/consts/urls.ts b/consts/urls.ts index 35c5d810e..67803f141 100644 --- a/consts/urls.ts +++ b/consts/urls.ts @@ -1,31 +1,62 @@ -// TODO: part of PATH -export const SETTINGS_PATH = '/settings'; - export const PATH = { HOME: '/', + CREATE: '/create', KEYS: '/keys', KEYS_SUBMIT: '/keys/submit', KEYS_REMOVE: '/keys/remove', + KEYS_EJECT: '/keys/eject', + KEYS_EXIT: '/keys/exit', KEYS_VIEW: '/keys/view', KEYS_NORMALIZE: '/keys/normalize', + + MONITORING: '/monitoring', + BOND: '/bond', BOND_CLAIM: '/bond/claim', BOND_ADD: '/bond/add', + BOND_REWARDS_HISTORY: '/bond/rewards-history', + BOND_REBASE_HISTORY: '/bond/rebase-history', BOND_UNLOCK: '/bond/unlock', - ROLES: '/roles', - ROLES_REWARDS: '/roles/reward-address', - ROLES_MANAGER: '/roles/manager-address', - ROLES_INBOX: '/roles/inbox', - STEALING: '/stealing', - STEALING_REPORT: '/stealing/report', - STEALING_CANCEL: '/stealing/cancel', + + SETTINGS: '/settings', + SETTINGS_ROLES: '/settings/roles', + SETTINGS_REWARDS_ADDRESS: '/settings/rewards-address', + SETTINGS_MANAGER_ADDRESS: '/settings/manager-address', + SETTINGS_CLAIMER: '/settings/claimer', + SETTINGS_SPLITS: '/settings/splits', + SETTINGS_INBOX: '/settings/inbox', + SETTINGS_METADATA: '/settings/metadata', + + DELAYED_PENALTY: '/delayed-penalty', + DELAYED_PENALTY_REPORT: '/delayed-penalty/report', + DELAYED_PENALTY_CANCEL: '/delayed-penalty/cancel', + + TYPE: '/type', + TYPE_ICS_CLAIM: '/type/ics-claim', + TYPE_ICS_SYSTEM: '/type/ics-system', + TYPE_ICS_APPLY: '/type/ics-apply', + TYPE_ICS_PARAMETERS: '/type/ics-parameters', + TYPE_PARAMETERS: '/type/parameters', + + TYPE_DVT_DESCRIPTION: '/type/idvtc-description', + TYPE_DVT_APPLY: '/type/idvtc-apply', + TYPE_DVT_PARAMETERS: '/type/idvtc-parameters', + TYPE_DVT_CLAIM: '/type/idvtc-claim', SURVEYS: '/surveys', SURVEYS_CONTACTS: '/surveys/contacts', SURVEYS_EXPERIENCE: '/surveys/experience', SURVEYS_HOW_DID_YOU_LEARN_CSM: '/surveys/learn-csm', SURVEYS_SETUP: '/surveys/setup', + SURVEYS_DELEGATES: '/surveys/delegates', + SURVEYS_DELEGATOR: '/surveys/delegator', + + GROUP: '/group', + + WRAPPED_SHARE: '/wrapped-2025/share', + + QA_CONFIG: '/qa-config', }; export type PATH = (typeof PATH)[keyof typeof PATH]; diff --git a/docs/component-rules.md b/docs/component-rules.md new file mode 100644 index 000000000..e9e9e17ed --- /dev/null +++ b/docs/component-rules.md @@ -0,0 +1,359 @@ +# Component Architecture Rules and Patterns + +This document outlines the established patterns and rules for components in the Lido CSM codebase, based on analysis of both `shared/components/` and `features/` directories. + +## File Organization and Naming + +### Directory Structure + +``` +shared/components/ +├── [component-name]/ # kebab-case directory names +│ ├── index.ts # barrel exports +│ ├── [component-name].tsx # main component file +│ ├── styles.ts # styling (or style.ts for simple components) +│ └── types.ts # optional type definitions +``` + +### File Naming Conventions + +- **Directories**: kebab-case (`accordion-navigatable`, `input-amount`) +- **Component files**: `{component-name}.tsx` matching directory name +- **Style files**: `styles.ts` (complex) or `style.ts` (simple) or `styles.tsx` (with JSX) +- **Type files**: `types.ts` (when needed) +- **Index files**: `index.ts` for re-exports + +## Component Structure Patterns + +### Basic Component Pattern + +```typescript +import { FC, ReactNode } from 'react'; +import { ComponentNameStyled } from './styles'; + +type Props = { + children?: ReactNode; + variant?: 'default' | 'warning'; + big?: boolean; +}; + +export const ComponentName: FC = ({ + children, + variant = 'default', + big = false, + ...props +}) => ( + + {children} + +); +``` + +### Compound Component Pattern + +```typescript +// For related components (like FAQ items) +export const Faq = ({ items }) => ( +
+ {items.map(item => ( + + ))} +
+); + +export const FaqItem = ({ title, content }) => ( +
+ {title} + {content} +
+); +``` + +## Styling Patterns + +### Styled-Components with Theme Integration + +```typescript +// styles.ts +import styled, { css } from 'styled-components'; +import { Block } from '@lidofinance/lido-ui'; + +const VARIANTS = { + default: css` + background: var(--lido-color-background); + `, + warning: css` + background: var(--lido-color-warning); + `, +}; + +export const ComponentStyled = styled(Block)<{ + $variant?: keyof typeof VARIANTS; + $big?: boolean; +}>` + display: flex; + gap: ${({ theme }) => theme.spaceMap.md}px; + padding: ${({ theme }) => theme.spaceMap.lg}px; + + ${({ $variant }) => $variant && VARIANTS[$variant]} + ${({ $big }) => + $big && + css` + font-size: ${({ theme }) => theme.fontSizesMap.lg}px; + `} +`; +``` + +### Styled-Component Props Rules + +- **Dollar prefix**: All styled-component props use `$` prefix (`$variant`, `$big`, `$gap`) +- **Boolean props**: Use direct boolean values (`$loading`, `$secondary`) +- **Variant props**: Use union types from variant objects + +## TypeScript Patterns + +### Props Type Definition + +```typescript +// Inline type definitions (preferred) +type ComponentProps = { + title?: ReactNode; + variant?: 'default' | 'warning'; + big?: boolean; +} & Omit, 'children'>; + +// OR for complex components +interface ComponentProps { + onSubmit: (data: FormData) => void; + loading?: boolean; + disabled?: boolean; +} +``` + +### Generic Component Pattern + +```typescript +type Component = ComponentProps & { + customProp?: string; +}; +``` + +### ForwardRef Pattern (for inputs) + +```typescript +export const InputComponent = forwardRef( + ({ value, onChange, ...props }, ref) => ( + + ) +); +``` + +## Export/Import Patterns + +### Index File Exports + +```typescript +// index.ts - barrel exports +export * from './component-name'; +export { ComponentName } from './component-name'; + +// For multiple related exports +export * from './component-name'; +export * from './sub-component'; +``` + +### Import Patterns + +```typescript +// Named imports (preferred) +import { Text, Button } from '@lidofinance/lido-ui'; +import { Stack } from '../stack'; + +// Type-only imports +import type { ComponentProps, FC } from 'react'; +``` + +## Feature-Based Architecture + +### Feature Structure + +``` +features/ +├── [feature-name]/ +│ ├── index.ts # feature exports +│ ├── [feature-name].tsx # main feature component +│ ├── [feature-name]-page.tsx # page wrapper +│ └── [feature-name]-form/ # form-specific logic +│ ├── context/ # form state management +│ ├── controls/ # form controls +│ ├── hooks/ # feature-specific hooks +│ └── [feature-name]-form.tsx +``` + +### Form Architecture Pattern + +```typescript +// Form Provider (context/[form-name]-form-provider.tsx) +export const FormProvider: FC = ({ children }) => { + const [networkData, revalidate] = useFormNetworkData(); + const validationResolver = useFormValidation(networkData); + const formObject = useForm({ + resolver: validationResolver, + mode: 'onChange', + }); + + return ( + + + + {children} + + + + ); +}; +``` + +### Form Validation Pattern + +```typescript +// use-[form-name]-validation.ts +export const useFormValidation = (networkData: NetworkData) => { + const dataPromise = useAwaitNetworkData(networkData); + + return useCallback>( + async (values) => { + try { + const networkContext = await dataPromise; + // Validation logic + return { values, errors: {} }; + } catch (error) { + return handleResolverValidationError(error, 'FormName', 'defaultField'); + } + }, + [dataPromise], + ); +}; +``` + +### Form Submission Pattern + +```typescript +// use-[form-name]-submit.ts +export const useFormSubmit = ({ onConfirm, onRetry }) => { + const { csm } = useLidoSDK(); + const { txModalStages } = useTxModalStages(); + + const submit = useCallback( + async (formData, networkData) => { + const callback: TransactionCallback = async ({ stage, payload }) => { + switch (stage) { + case TransactionCallbackStage.SIGN: + txModalStages.sign(formData); + break; + case TransactionCallbackStage.RECEIPT: + txModalStages.pending(formData, payload.hash); + break; + case TransactionCallbackStage.DONE: + txModalStages.success(payload.result, payload.hash); + break; + case TransactionCallbackStage.ERROR: + txModalStages.failed(payload.error, onRetry); + break; + } + }; + + await csm.operation({ ...formData, callback }); + return true; + }, + [csm, txModalStages, onConfirm, onRetry], + ); + + return { submit }; +}; +``` + +## Component Naming Conventions + +### Shared Components + +- **Descriptive names**: `AccordionNavigatable`, `AmountWithPrice`, `ExternalButtonLink` +- **Suffix patterns**: `Styled` for styled components, `Hook` for hook components +- **Boolean props**: `big`, `loading`, `disabled`, `warning` + +### Feature Components + +- **Pages**: `[Feature]Page` (e.g., `AddBondPage`, `DashboardPage`) +- **Main components**: `[Feature]` (e.g., `AddBond`, `Dashboard`) +- **Forms**: `[Feature]Form` (e.g., `AddBondForm`, `SubmitKeysForm`) +- **Form controls**: Descriptive names (`AmountInput`, `SubmitButton`, `TokenSelect`) +- **Providers**: `[Feature]FormProvider` +- **Hooks**: `use[Feature][Purpose]` (e.g., `useAddBondSubmit`, `useAddBondValidation`) + +## Performance and Best Practices + +### Optimization Patterns + +- Use `forwardRef` for input components +- Implement `useCallback` for expensive operations +- Use `useMemo` for complex calculations +- Implement proper loading states + +### Error Handling + +- Graceful fallbacks (return `null` when required props missing) +- Try-catch blocks for parsing operations +- Consistent error messaging through validation utilities + +### Accessibility + +- Proper ARIA attributes +- Keyboard navigation support +- Screen reader considerations +- Semantic HTML structure + +## Integration Patterns + +### External Libraries + +- **Base components**: Extend `@lidofinance/lido-ui` components +- **Web3 integration**: Use `@lidofinance/lido-csm-sdk` for blockchain operations +- **Form handling**: React Hook Form with custom resolvers +- **Styling**: Styled-components with theme integration + +### Theme Integration + +```typescript +// Use theme properties +gap: ${({ theme }) => theme.spaceMap.md}px; +border-radius: ${({ theme }) => theme.borderRadiusesMap.md}px; +color: var(--lido-color-text); +``` + +## Common Anti-Patterns to Avoid + +1. **Don't** use direct DOM manipulation +2. **Don't** create styled-component props without `$` prefix +3. **Don't** mix file naming conventions (stick to kebab-case) +4. **Don't** create new validation patterns - use existing utilities +5. **Don't** bypass the form context architecture for forms +6. **Don't** create components without proper TypeScript types +7. **Don't** ignore accessibility requirements + +## Conclusion + +These patterns ensure: + +- **Consistency** across the codebase +- **Maintainability** through clear conventions +- **Type safety** with comprehensive TypeScript usage +- **Performance** through optimized patterns +- **Accessibility** through proper implementation +- **Developer experience** through predictable structure + +Follow these patterns when creating new components or modifying existing ones to maintain codebase quality and consistency. diff --git a/env-dynamics.mjs b/env-dynamics.mjs index 0061b6e15..c5c423a19 100644 --- a/env-dynamics.mjs +++ b/env-dynamics.mjs @@ -18,29 +18,50 @@ const toBoolean = (dataStr) => { /** @type string */ export const matomoHost = process.env.MATOMO_URL; /** @type number */ -export const defaultChain = parseInt(process.env.DEFAULT_CHAIN, 10) || 17000; -/** @type number[] */ - -export const supportedChains = process.env?.SUPPORTED_CHAINS?.split(',').map( - (chainId) => parseInt(chainId, 10), -) ?? [17000]; +export const defaultChain = parseInt(process.env.DEFAULT_CHAIN, 10) || 560048; /** @type string */ export const walletconnectProjectId = process.env.WALLETCONNECT_PROJECT_ID; /** @type boolean */ export const ipfsMode = toBoolean(process.env.IPFS_MODE); +// Parse comma-separated URL list: trim whitespace, strip trailing slashes, +// drop empty entries. Trailing `/` breaks some RPC providers (e.g. Infura). +const parseUrlList = (val) => + val + ?.split(',') + .map((s) => s.trim().replace(/\/+$/, '')) + .filter(Boolean) ?? []; + /** @type string[] */ -export const prefillUnsafeElRpcUrls1 = - process.env.PREFILL_UNSAFE_EL_RPC_URLS_1?.split(',') ?? []; +export const prefillUnsafeElRpcUrls1 = parseUrlList( + process.env.PREFILL_UNSAFE_EL_RPC_URLS_1, +); /** @type string[] */ -export const prefillUnsafeElRpcUrls17000 = - process.env.PREFILL_UNSAFE_EL_RPC_URLS_17000?.split(',') ?? []; +export const prefillUnsafeElRpcUrls560048 = parseUrlList( + process.env.PREFILL_UNSAFE_EL_RPC_URLS_560048, +); /** @type string */ export const widgetApiBasePathForIpfs = process.env.WIDGET_API_BASE_PATH_FOR_IPFS; +/** @type boolean */ +export const addressApiValidationEnabled = + !!process.env.VALIDATION_SERVICE_BASE_PATH; + +/** @type string */ +export const validationFilePath = process.env.VALIDATION_FILE_PATH; + +/** @type string */ +export const keysApiUrl = process.env.KEYS_API_URL; + +/** @type string */ +export const feesMonitoringApiUrl = process.env.FEES_MONITORING_API_URL; + +/** @type string[] */ +export const ipfsGateways = parseUrlList(process.env.IPFS_GATEWAYS); + /** @type string */ -export const surveyApi = process.env.SURVEY_API; +export const surveysApiUrl = process.env.SURVEYS_API_URL; diff --git a/faq/bond-1.md b/faq/bond-1.md deleted file mode 100644 index f4cc4ef44..000000000 --- a/faq/bond-1.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: What rewards do I get in CSM? ---- - -When CSM operators use the Lido protocol to run validators, they can receive two types of rewards: - -- **Node Operator rewards**: a share of rewards from staker locked stake amount, currently calculated pro-rata based on validators operated as a share of total protocol validators, with [possible reductions for bad performance](https://operatorportal.lido.fi/modules/community-staking-module#block-c6dc8d00f13243fcb17de3fa07ecc52c). -- **Bond rebase**: staking rewards pertaining to the bonded tokens (stETH). diff --git a/faq/bond-2.md b/faq/bond-2.md deleted file mode 100644 index e38bfc932..000000000 --- a/faq/bond-2.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: How often do I get rewards? ---- - -**Node Operator rewards** on mainnet are calculated and made claimable by the CSM Oracle **every 28 days**. Rewards do not have to be claimed during every reporting frame, and can be left to accumulate to be claimed later. - -**Bond rebase part** of the rewards come from stETH being a rebasing token and the bond being stored in stETH. After each Accounting Oracle report that happens on mainnet **every 225 epochs (24hrs)**, the share rate changes. Hence, the same amount of stETH shares will now be equal to a bigger stETH token balance. diff --git a/faq/bond-3.md b/faq/bond-3.md deleted file mode 100644 index 5659ec717..000000000 --- a/faq/bond-3.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Why didn’t I get rewards? -anchor: why-did-not-i-get-rewards ---- - -There are two main reasons of you getting no reward within a frame: - -1. If your validator’s performance was below the threshold within the CSM Performance Oracle frame (28 days for mainnet) the validator does not receive rewards for the given frame. Read more about [the CSM Performance Oracle](https://operatorportal.lido.fi/modules/community-staking-module#block-c6dc8d00f13243fcb17de3fa07ecc52c). -2. [Your Node Operator has stuck keys](https://operatorportal.lido.fi/modules/community-staking-module#block-0ed61a4c0a5a439bbb4be20e814b4e38) due to not exiting a validator requested for exit timely. diff --git a/faq/bond-4.md b/faq/bond-4.md deleted file mode 100644 index 4991f37c6..000000000 --- a/faq/bond-4.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Why add a bond? ---- - -Adding bond is a prevention measure to avoid Exit Request for your validators if they became unbonded. [Unbonded validators](https://docs.lido.fi/staking-modules/csm/guides/unbonded-validators) appear if the Node Operator's bond is no longer sufficient to cover all the validator keys uploaded to CSM by the Node Operator. - -If a [penalty](https://operatorportal.lido.fi/modules/community-staking-module#block-3951aa72ba1e471bafe95b40fef65d2b) was already applied, there is a relatively short period of time until the next VEBO report, which most likely will contain a validator Exit Request. During this period in between penalty application and the next VEBO report, Node Operators must top up bond to avoid Exit Requests for their validator(s). - -**Warning:** If the unbonded validator has already been requested to exit, Node Operators can only exit it. The bond top-up after the Exit Request will not reverse the Exit Request. diff --git a/faq/bond-5.md b/faq/bond-5.md deleted file mode 100644 index 3c6602435..000000000 --- a/faq/bond-5.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: How to claim ETH using a withdrawal NFT -anchor: how-to-claim-eth ---- - -Claiming bond and rewards in a form of ETH constitutes an stETH withdrawal process (unstake). - -The withdrawal process consists of several steps you need to do: - -- **Submit a withdrawal request** by choosing ETH as a token for bond/rewards claim. As a result of this step, you will receive a withdrawal NFT. -- **Claim your ETH** after request fulfilment. The fulfilment process takes 1-5 days (or longer), [depending on a variety of factors](https://help.lido.fi/en/articles/7858315-how-long-does-an-ethereum-withdrawal-take). To know if your ETH is ready to be claimed you, can check its status on the [Claim page](https://stake.lido.fi/withdrawals/claim). If your request is marked as “**Ready to claim**”, it is time for you to get your ETH back. - -For more information about withdrawals, [follow the page](https://help.lido.fi/en/collections/3993867-ethereum-withdrawals). diff --git a/faq/images/curve-def-dark.png b/faq/images/curve-def-dark.png new file mode 100644 index 000000000..7481f4927 Binary files /dev/null and b/faq/images/curve-def-dark.png differ diff --git a/faq/images/curve-def.png b/faq/images/curve-def.png new file mode 100644 index 000000000..9a0aed0ea Binary files /dev/null and b/faq/images/curve-def.png differ diff --git a/faq/images/curve-ics-dark.png b/faq/images/curve-ics-dark.png new file mode 100644 index 000000000..f29026512 Binary files /dev/null and b/faq/images/curve-ics-dark.png differ diff --git a/faq/images/curve-ics.png b/faq/images/curve-ics.png new file mode 100644 index 000000000..e24fdd968 Binary files /dev/null and b/faq/images/curve-ics.png differ diff --git a/faq/index.ts b/faq/index.ts new file mode 100644 index 000000000..47318c998 --- /dev/null +++ b/faq/index.ts @@ -0,0 +1,152 @@ +import { isModuleCM } from 'consts'; +import { + BondRewards1, + BondRewards2, + BondRewards3, + BondRewards4, + BondRewards5, + Keys1, + Keys10, + Keys11, + Keys12, + Keys13, + Keys14, + Keys15, + Keys2, + Keys3, + Keys4, + Keys5, + Keys6, + Keys7, + Keys8, + Keys9, + LockedBond1, + LockedBond2, + LockedBond3, + Main1, + Main2, + Main3, + Main4, + Main5, + Main6, + Main7, + Main8, + Monitoring1, + Monitoring2, + Monitoring3, + Monitoring4, + Monitoring5, + OperatorType1, + OperatorType2, + Roles1, + Roles2, + Roles3, + Roles4, + Roles5, +} from './items'; +import { + CmBondRewards1, + CmBondRewards2, + CmBondRewards3, + CmBondRewards4, + CmKeys1, + CmKeys10, + CmKeys2, + CmKeys3, + CmKeys4, + CmKeys5, + CmKeys6, + CmKeys7, + CmKeys8, + CmKeys9, + CmLockedBond1, + CmLockedBond2, + CmLockedBond3, + CmMain1, + CmMain2, + CmMain3, + CmOperatorType1, + CmOperatorType2, + CmRoles1, + CmRoles2, + CmRoles3, + CmRoles4, + CmRoles5, +} from './items-cm'; + +const FAQ_OPERATOR_TYPE_CSM = [OperatorType1, OperatorType2]; +const FAQ_OPERATOR_TYPE_CM = [CmOperatorType1, CmOperatorType2]; + +const FAQ_ROLES_CSM = [Roles1, Roles2, Roles3, Roles4, Roles5]; +const FAQ_ROLES_CM = [CmRoles1, CmRoles2, CmRoles3, CmRoles4, CmRoles5]; + +const FAQ_BOND_CSM = [ + BondRewards1, + BondRewards2, + BondRewards3, + BondRewards4, + BondRewards5, +]; +const FAQ_BOND_CM = [ + CmBondRewards1, + CmBondRewards2, + CmBondRewards3, + CmBondRewards4, +]; + +const FAQ_LOCKED_CSM = [LockedBond1, LockedBond2, LockedBond3]; +const FAQ_LOCKED_CM = [CmLockedBond1, CmLockedBond2, CmLockedBond3]; + +const FAQ_MAIN_CSM = [Main1, Main2, Main3, Main4, Main5, Main6, Main7, Main8]; +const FAQ_MAIN_CM = [CmMain1, CmMain2, CmMain3]; + +const FAQ_MONITORING_CSM = [ + Monitoring1, + Monitoring2, + Monitoring3, + Monitoring4, + Monitoring5, +]; +const FAQ_MONITORING_CM: typeof FAQ_MONITORING_CSM = []; + +const FAQ_KEYS_CSM = [ + Keys1, + Keys2, + Keys3, + Keys4, + Keys5, + Keys6, + Keys7, + Keys8, + Keys9, + Keys10, + Keys11, + Keys12, + Keys13, + Keys14, + Keys15, +]; +const FAQ_KEYS_CM = [ + CmKeys1, + CmKeys2, + CmKeys3, + CmKeys4, + CmKeys10, + CmKeys5, + CmKeys6, + CmKeys7, + CmKeys8, + CmKeys9, +]; + +export const FAQ_OPERATOR_TYPE = isModuleCM + ? FAQ_OPERATOR_TYPE_CM + : FAQ_OPERATOR_TYPE_CSM; +export const FAQ_ROLES = isModuleCM ? FAQ_ROLES_CM : FAQ_ROLES_CSM; +export const FAQ_BOND = isModuleCM ? FAQ_BOND_CM : FAQ_BOND_CSM; +export const FAQ_LOCKED = isModuleCM ? FAQ_LOCKED_CM : FAQ_LOCKED_CSM; +export const FAQ_MAIN = isModuleCM ? FAQ_MAIN_CM : FAQ_MAIN_CSM; +export const FAQ_MONITORING = isModuleCM + ? FAQ_MONITORING_CM + : FAQ_MONITORING_CSM; +export const FAQ_KEYS = isModuleCM ? FAQ_KEYS_CM : FAQ_KEYS_CSM; diff --git a/faq/items-cm/cm-bond-rewards-1.tsx b/faq/items-cm/cm-bond-rewards-1.tsx new file mode 100644 index 000000000..def082591 --- /dev/null +++ b/faq/items-cm/cm-bond-rewards-1.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmBondRewards1: Faq = { + title: 'What rewards do I get in CM?', + anchor: 'what-rewards-do-i-get-in-cm', + content: ( +
+

Running validators through CMv2 gives you two types of rewards:

+
    +
  • + Protocol fee: a share of staking rewards based on + your validator count as a portion of total Lido validators. +
  • +
  • + Bond rebase: staking rewards from your posted stETH + bond, accruing daily even before your validators go live. +
  • +
+

+ + See Rewards + +

+
+ ), +}; diff --git a/faq/items-cm/cm-bond-rewards-2.tsx b/faq/items-cm/cm-bond-rewards-2.tsx new file mode 100644 index 000000000..1149a0aaa --- /dev/null +++ b/faq/items-cm/cm-bond-rewards-2.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmBondRewards2: Faq = { + title: 'How often do I get rewards?', + anchor: 'how-often-do-i-get-rewards', + content: ( +
+

+ Bond rebases accrue daily. Operator fees are calculated per reporting + frame of 14 days. +

+

+ + See Rewards + +

+
+ ), +}; diff --git a/faq/items-cm/cm-bond-rewards-3.tsx b/faq/items-cm/cm-bond-rewards-3.tsx new file mode 100644 index 000000000..dab918c35 --- /dev/null +++ b/faq/items-cm/cm-bond-rewards-3.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmBondRewards3: Faq = { + title: 'Why did I not get rewards?', + anchor: 'why-didnt-i-get-rewards', + content: ( +
+

+ Common reasons for not getting rewards or getting less than expected: +

+
    +
  • The Oracle report is delayed.
  • +
  • + Your keys are still waiting for deposits and have not been activated + yet. +
  • +
  • + Your bond is below the required minimum, leaving some keys unbonded. +
  • +
  • You have locked bond that has not been compensated.
  • +
+
+ ), +}; diff --git a/faq/items-cm/cm-bond-rewards-4.tsx b/faq/items-cm/cm-bond-rewards-4.tsx new file mode 100644 index 000000000..14a70ad9d --- /dev/null +++ b/faq/items-cm/cm-bond-rewards-4.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; +import { getExternalLinks } from 'consts/external-links'; + +const { stakeWidget } = getExternalLinks(); + +export const CmBondRewards4: Faq = { + title: 'How to claim ETH using a withdrawal NFT?', + anchor: 'how-to-claim-eth-using-a-withdrawal-nft', + content: ( +
+

+ Claiming bond or rewards as ETH is an stETH withdrawal (unstake). The + withdrawal process consists of several steps you need to do: +

+
    +
  • + Submit a withdrawal request by choosing ETH as a + token for bond/rewards claim. As a result of this step, you will + receive a withdrawal NFT. +
  • +
  • + Claim your ETH after request fulfilment. The + fulfilment process takes some time,{' '} + + depending on a variety of factors + + . To know if your ETH is ready to be claimed you, can check its status + on the{' '} + + Claim page + + . If your request is marked as “ + Ready to claim”, it is time for you to get your + ETH back. +
  • +
+

+ For more information about withdrawals,{' '} + + follow the page + + . +

+

+ Please note addresses in the Reward Splitter will only receive stETH. +

+
+ ), +}; diff --git a/faq/items-cm/cm-keys-1.tsx b/faq/items-cm/cm-keys-1.tsx new file mode 100644 index 000000000..4360af192 --- /dev/null +++ b/faq/items-cm/cm-keys-1.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmKeys1: Faq = { + title: 'How much bond is needed?', + anchor: 'how-much-bond-is-needed', + content: ( +
+

+ Bond is required for every 0x02 key. The exact amount depends on your + operator type and can be found in{' '} + + the Bond section + + . +

+
+ ), +}; diff --git a/faq/items-cm/cm-keys-10.tsx b/faq/items-cm/cm-keys-10.tsx new file mode 100644 index 000000000..ad5f86226 --- /dev/null +++ b/faq/items-cm/cm-keys-10.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmKeys10: Faq = { + title: 'When does a validator become active?', + anchor: 'when-does-a-validator-become-active', + content: ( +
+

+ After key submission, and if keys have been successfully validated, two + actions are required for a validator to be activated: +

+
    +
  1. + Deposit by Lido Protocol: The time to deposit a + validator is unpredictable and depends on factors such as total stake + inflows and outflows, gas considerations, module shares, node + operator’s current and target share, etc. +
  2. +
  3. + Activation on Ethereum Network: Once deposited, the + validator enters the Beacon Chain activation queue. The time to + activation depends on the total number of validators in the queue + awaiting activation and the rate of queue processing, which varies + based on the total number of active Ethereum validators. +
  4. +
+
+ ), +}; diff --git a/faq/items-cm/cm-keys-2.tsx b/faq/items-cm/cm-keys-2.tsx new file mode 100644 index 000000000..6481dc042 --- /dev/null +++ b/faq/items-cm/cm-keys-2.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmKeys2: Faq = { + title: "Can't see the key for deletion?", + anchor: 'cant-see-the-key-for-deletion', + content: ( +
+

+ Only keys that have not been deposited yet can be removed. If a key is + already active, you need to exit the validator. +

+

+ + See Bond and Key Management + +

+
+ ), +}; diff --git a/faq/items-cm/cm-keys-3.tsx b/faq/items-cm/cm-keys-3.tsx new file mode 100644 index 000000000..45824be7d --- /dev/null +++ b/faq/items-cm/cm-keys-3.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmKeys3: Faq = { + title: + 'What is the difference between removing, exiting, and ejecting a key?', + anchor: 'what-is-the-difference-between-removing-exiting-and-ejecting-a-key', + content: ( +
+

Removing a key deletes it before it has been deposited.

+

+ Exiting a validator is a voluntary action performed through your + consensus client. It starts the exit process on the Beacon chain. +

+

+ Ejecting a validator triggers the exit through EIP-7002 (Triggerable + Withdrawals). This is done by the protocol when required or can be + triggered by a Node Operator in case of emergency. +

+

+ + See Bond and Key Management + +

+
+ ), +}; diff --git a/faq/items-cm/cm-keys-4.tsx b/faq/items-cm/cm-keys-4.tsx new file mode 100644 index 000000000..9a86d8ce7 --- /dev/null +++ b/faq/items-cm/cm-keys-4.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmKeys4: Faq = { + title: 'Why a key can get ejected?', + anchor: 'why-a-key-can-get-ejected', + content: ( +
+

+ The protocol can eject your validator if an exit request from the + Validators Exit Bus Oracle (VEBO) was not processed within the required + window. +

+

+ You can also eject your own validator voluntarily using Triggerable + Withdrawals. +

+
+ ), +}; diff --git a/faq/items-cm/cm-keys-5.tsx b/faq/items-cm/cm-keys-5.tsx new file mode 100644 index 000000000..1d38d250f --- /dev/null +++ b/faq/items-cm/cm-keys-5.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmKeys5: Faq = { + title: 'When does a validator become withdrawn?', + anchor: 'when-does-a-validator-become-withdrawn', + content: ( +
+

+ A validator is withdrawn after exiting the consensus layer and having + its balance swept to the withdrawal address. There are three stages: +

+
    +
  1. + Exit queue: when the exit is initiated, the validator enters the exit + queue. Wait time depends on how many validators are exiting. +
  2. +
  3. + Withdrawable state: after leaving the active set, there is a mandatory + delay of 256 epochs (~27 hours) before the balance can be swept. +
  4. +
  5. + Sweep: once the withdrawable epoch is reached, the balance is + transferred to the withdrawal address. +
  6. +
+

+ Once the withdrawal is reported to the module, any pending penalties are + applied and the remaining bond is released. +

+
+ ), +}; diff --git a/faq/items-cm/cm-keys-6.tsx b/faq/items-cm/cm-keys-6.tsx new file mode 100644 index 000000000..a37e6534a --- /dev/null +++ b/faq/items-cm/cm-keys-6.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmKeys6: Faq = { + title: 'What are the possible key statuses?', + anchor: 'what-are-the-possible-key-statuses', + content: ( +
+

Keys in CMv2 can have the following statuses:

+
    +
  • + Depositable: Key is valid and bond is sufficient. + Pending deposit from Lido Protocol +
  • +
  • + Pending activation: Key has been deposited and is + awaiting activation on the beacon chain +
  • +
  • + Active: Key is active on the beacon chain +
  • +
  • + Exited: Key has been exited +
  • +
  • + Withdrawn: Key has been exited and ETH has been + returned to the protocol +
  • +
  • + Unbonded: Bond is insufficient for this key, which + can be Active or otherwise +
  • +
  • + Exit requested: An exit has been requested by{' '} + + VEBO + {' '} + but the validator has not yet exited +
  • +
  • + Duplicated: Key has been uploaded twice either to the + Lido protocol or Ethereum CL +
  • +
  • + Invalid: Uploaded key has an invalid signature +
  • +
+

+ + See Bond and Key Management + +

+
+ ), +}; diff --git a/faq/items-cm/cm-keys-7.tsx b/faq/items-cm/cm-keys-7.tsx new file mode 100644 index 000000000..3c207f20d --- /dev/null +++ b/faq/items-cm/cm-keys-7.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmKeys7: Faq = { + title: 'What is the key ejection cost?', + anchor: 'what-is-the-key-ejection-cost', + content: ( +
+

+ The key ejection cost is the network fee required to cover the cost to + trigger a withdrawal from the Execution Layer. It will be deducted from + your wallet balance. +

+
+ ), +}; diff --git a/faq/items-cm/cm-keys-8.tsx b/faq/items-cm/cm-keys-8.tsx new file mode 100644 index 000000000..9411a9c47 --- /dev/null +++ b/faq/items-cm/cm-keys-8.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmKeys8: Faq = { + title: 'What happens to my keys if my bond drops below the required amount?', + anchor: 'what-happens-to-my-keys-if-my-bond-drops-below-the-required-amount', + content: ( +
+

+ If your bond falls below the required minimum, some of your keys become{' '} + Unbonded and will not receive new deposits; if the key + was already deposited or active, an exit will be requested. +

+

To solve this you can either top up the bond, or exit the key.

+
+ ), +}; diff --git a/faq/items-cm/cm-keys-9.tsx b/faq/items-cm/cm-keys-9.tsx new file mode 100644 index 000000000..0011fcc8a --- /dev/null +++ b/faq/items-cm/cm-keys-9.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmKeys9: Faq = { + title: 'When is the bond released after a key is exited or ejected?', + anchor: 'when-is-the-bond-released-after-a-key-is-exited-or-ejected', + content: ( +
+

+ Bond is released after the validator has fully withdrawn from the Beacon + chain. The timing depends on the Ethereum withdrawal queue. +

+
+ ), +}; diff --git a/faq/items-cm/cm-locked-bond-1.tsx b/faq/items-cm/cm-locked-bond-1.tsx new file mode 100644 index 000000000..2f348f9ec --- /dev/null +++ b/faq/items-cm/cm-locked-bond-1.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmLockedBond1: Faq = { + title: 'Why is the bond locked?', + anchor: 'why-is-the-bond-locked', + content: ( +
+

+ Bond gets locked when the Curated Module Committee reports a penalty on + your Node Operator, for example after a slashing event or an EL rewards + violation. The locked amount covers the losses the protocol incurred. +

+

+ While bond is locked, any shortfall may leave keys unbonded and stop new + stake allocations. +

+

+ + See Penalties + +

+
+ ), +}; diff --git a/faq/items-cm/cm-locked-bond-2.tsx b/faq/items-cm/cm-locked-bond-2.tsx new file mode 100644 index 000000000..ca3d0e2d0 --- /dev/null +++ b/faq/items-cm/cm-locked-bond-2.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmLockedBond2: Faq = { + title: 'How to unlock the bond?', + anchor: 'how-to-unlock-the-bond', + content: ( +
+

+ Go to Bond and Rewards section on the CMv2 widget, open the Unlock Bond + tab, and compensate the locked amount. Once compensated, the lock is + released and your node operator resumes normal operation. +

+

+ If you believe the penalty was applied incorrectly, open a public + discussion in the Lido research forum. +

+
+ ), +}; diff --git a/faq/items-cm/cm-locked-bond-3.tsx b/faq/items-cm/cm-locked-bond-3.tsx new file mode 100644 index 000000000..4fc346801 --- /dev/null +++ b/faq/items-cm/cm-locked-bond-3.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmLockedBond3: Faq = { + title: 'Consequences of not compensating?', + anchor: 'consequences-of-not-compensating', + content: ( +
+

+ If you do not compensate the locked bond within the 60-day window, an + EasyTrack motion is submitted to confirm the penalty. If enacted, the + locked funds are permanently burned to cover losses for stETH holders. +

+

+ While waiting, any bond shortfall leaves your keys unbonded and freezes + new stake allocations. +

+

+ + See Penalties + +

+
+ ), +}; diff --git a/faq/items-cm/cm-main-1.tsx b/faq/items-cm/cm-main-1.tsx new file mode 100644 index 000000000..c4bfff47b --- /dev/null +++ b/faq/items-cm/cm-main-1.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmMain1: Faq = { + title: 'What do node operators receive in CM?', + anchor: 'what-do-node-operators-receive-in-cm', + content: ( +
+

Node operators benefit from two reward streams:

+
    +
  • + Protocol fee: a share of staking rewards. +
  • +
  • + Bond rebase: daily stETH staking rewards on your + posted bond, even before your validators go live. +
  • +
+

+ + See Rewards + +

+
+ ), +}; diff --git a/faq/items-cm/cm-main-2.tsx b/faq/items-cm/cm-main-2.tsx new file mode 100644 index 000000000..8615295cc --- /dev/null +++ b/faq/items-cm/cm-main-2.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmMain2: Faq = { + title: 'What is the difference between CM and CMv2?', + anchor: 'what-is-the-difference-between-cm-and-cmv2', + content: ( +
+

+ CMv2 is the next version of the Curated Module. It is built for 0x02 + validators with balances up to 2048 ETH, introduces a bond requirement + for node operators, adds operator types with different parameters, and + includes on-chain accountability mechanisms. +

+

+ CMv1 was fully reputation-based with no distinction between operators + and designed around 0x01 validators. +

+

+ + See Context and Background + +

+
+ ), +}; diff --git a/faq/items-cm/cm-main-3.tsx b/faq/items-cm/cm-main-3.tsx new file mode 100644 index 000000000..df50d20d4 --- /dev/null +++ b/faq/items-cm/cm-main-3.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmMain3: Faq = { + title: 'Can I change my node operator name or description later?', + anchor: 'can-i-change-my-node-operator-name-or-description-later', + content: ( +
+

+ Yes. Both the name and description fields can be edited by the operator + on the Settings → Meta Data tab, or the Curated Module Committee + after creation. +

+
+ ), +}; diff --git a/faq/items-cm/cm-operator-type-1.tsx b/faq/items-cm/cm-operator-type-1.tsx new file mode 100644 index 000000000..2c28bffd5 --- /dev/null +++ b/faq/items-cm/cm-operator-type-1.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmOperatorType1: Faq = { + title: 'What is a sub-node operator type and how many can I create?', + anchor: 'what-is-a-sub-node-operator-type-and-how-many-can-i-create', + content: ( +
+

+ A sub-node operator is a unique operator within your operator group. + Each sub-operator has its own manager and rewards addresses, bond, and + keys. You can run multiple sub-operators of different types under a + single group. +

+

+ Creating sub-operators is a permissioned action governed by the Curated + Module Committee. +

+

+ + See Node Operator Types + +

+
+ ), +}; diff --git a/faq/items-cm/cm-operator-type-2.tsx b/faq/items-cm/cm-operator-type-2.tsx new file mode 100644 index 000000000..16ab30529 --- /dev/null +++ b/faq/items-cm/cm-operator-type-2.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmOperatorType2: Faq = { + title: 'How do I move from PO to PTO?', + anchor: 'how-do-i-move-from-po-to-pto', + content: ( +
+

+ You can move from PO to PTO if you meet{' '} + + the criteria + {' '} + set by the Curated Module Committee. +

+
+ ), +}; diff --git a/faq/items-cm/cm-roles-1.tsx b/faq/items-cm/cm-roles-1.tsx new file mode 100644 index 000000000..9f5e53393 --- /dev/null +++ b/faq/items-cm/cm-roles-1.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmRoles1: Faq = { + title: 'What are Rewards and Manager Addresses?', + anchor: 'what-are-rewards-and-manager-addresses', + content: ( +
+

Every sub-operator has two required addresses:

+
    +
  • + Manager Address: the primary control address. It can add and remove + keys, top up bond, and propose address changes. +
  • +
  • + Rewards Address: where your staking rewards are sent. It can also + claim rewards and request the Rewards Address change. +
  • +
+

+ Additionally, a Rewards Claimer and Rewards Splitter can be set to + trigger reward claiming from a different address or send rewards to + multiple addresses on claim. +

+

+ + See Roles + +

+
+ ), +}; diff --git a/faq/items-cm/cm-roles-2.tsx b/faq/items-cm/cm-roles-2.tsx new file mode 100644 index 000000000..c86bdde8c --- /dev/null +++ b/faq/items-cm/cm-roles-2.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmRoles2: Faq = { + title: 'How to accept a change in address request?', + anchor: 'how-to-accept-a-change-in-address-request', + content: ( +
+

+ Connect to the CMv2 widget with the new address, navigate to Roles, open + the pending request, and confirm it. +

+
+ ), +}; diff --git a/faq/items-cm/cm-roles-3.tsx b/faq/items-cm/cm-roles-3.tsx new file mode 100644 index 000000000..2d9d84fb4 --- /dev/null +++ b/faq/items-cm/cm-roles-3.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmRoles3: Faq = { + title: 'What to do if the change is submitted to a wrong address?', + anchor: 'what-to-do-if-the-change-is-submitted-to-a-wrong-address', + content: ( +
+

+ Submit a new proposal from the Manager Address before the wrong address + accepts. The new proposal overwrites the pending one. +

+
+ ), +}; diff --git a/faq/items-cm/cm-roles-4.tsx b/faq/items-cm/cm-roles-4.tsx new file mode 100644 index 000000000..a15e24ef7 --- /dev/null +++ b/faq/items-cm/cm-roles-4.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const CmRoles4: Faq = { + title: 'What happens to rewards after changing the Rewards address?', + anchor: 'what-happens-to-rewards-after-changing-the-rewards-address', + content: ( +
+

+ Rewards already claimed to the previous address stay there. After the + change, all new rewards as well as the claimed bond go to the new + address. +

+
+ ), +}; diff --git a/faq/items-cm/cm-roles-5.tsx b/faq/items-cm/cm-roles-5.tsx new file mode 100644 index 000000000..8f4518a4b --- /dev/null +++ b/faq/items-cm/cm-roles-5.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const CmRoles5: Faq = { + title: 'What’s the difference between Rewards Claimer and Rewards Splitter?', + anchor: 'whats-the-difference-between-rewards-claimer-and-rewards-splitter', + content: ( +
+

+ The Rewards Claimer is a separate address that can pull rewards on your + behalf, useful if you want to automate or delegate reward claiming + without exposing your Manager or Rewards Address. +

+

+ The Rewards Splitter defines how your Node Operator rewards are + distributed across multiple recipient addresses. It does not apply to + bond rebase rewards. +

+

+ + See Roles + +

+
+ ), +}; diff --git a/faq/items-cm/index.ts b/faq/items-cm/index.ts new file mode 100644 index 000000000..2b132e956 --- /dev/null +++ b/faq/items-cm/index.ts @@ -0,0 +1,27 @@ +export * from './cm-bond-rewards-1'; +export * from './cm-bond-rewards-2'; +export * from './cm-bond-rewards-3'; +export * from './cm-bond-rewards-4'; +export * from './cm-keys-1'; +export * from './cm-keys-2'; +export * from './cm-keys-3'; +export * from './cm-keys-4'; +export * from './cm-keys-5'; +export * from './cm-keys-6'; +export * from './cm-keys-7'; +export * from './cm-keys-8'; +export * from './cm-keys-9'; +export * from './cm-keys-10'; +export * from './cm-locked-bond-1'; +export * from './cm-locked-bond-2'; +export * from './cm-locked-bond-3'; +export * from './cm-main-1'; +export * from './cm-main-2'; +export * from './cm-main-3'; +export * from './cm-operator-type-1'; +export * from './cm-operator-type-2'; +export * from './cm-roles-1'; +export * from './cm-roles-2'; +export * from './cm-roles-3'; +export * from './cm-roles-4'; +export * from './cm-roles-5'; diff --git a/faq/items/bond-rewards-1.tsx b/faq/items/bond-rewards-1.tsx new file mode 100644 index 000000000..3996afb7a --- /dev/null +++ b/faq/items/bond-rewards-1.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const BondRewards1: Faq = { + title: 'What rewards do I get in CSM?', + anchor: 'what-rewards-do-i-get-in-csm', + content: ( +
+

+ When CSM operators use the Lido protocol to run validators, they can + receive two types of rewards: +

+
    +
  • + Node Operator rewards: a share of rewards from staker + locked stake amount, currently calculated pro-rata based on validators + operated as a share of total protocol validators, with{' '} + + possible reductions for bad performance + + . +
  • +
  • + Bond rebase: staking rewards pertaining to the bonded + tokens (stETH). +
  • +
+
+ ), +}; diff --git a/faq/items/bond-rewards-2.tsx b/faq/items/bond-rewards-2.tsx new file mode 100644 index 000000000..b175f627c --- /dev/null +++ b/faq/items/bond-rewards-2.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { + FaqChainName, + FaqFrameDuration, + FaqRebaseDuration, +} from 'shared/components'; +import { Faq } from 'types'; + +export const BondRewards2: Faq = { + title: 'How often do I get rewards?', + anchor: 'how-often-do-i-get-rewards', + content: ( +
+

+ Node Operator rewards on are + calculated and made claimable by the CSM Oracle{' '} + + every + + . Rewards do not have to be claimed during every reporting frame, and + can be left to accumulate to be claimed later. +

+

+ Bond rebase part of the rewards come from stETH being a + rebasing token and the bond being stored in stETH. After each Accounting + Oracle report that happens on {' '} + + every + + , the share rate changes. Hence, the same amount of stETH shares will + now be equal to a bigger stETH token balance. +

+
+ ), +}; diff --git a/faq/items/bond-rewards-3.tsx b/faq/items/bond-rewards-3.tsx new file mode 100644 index 000000000..e63b2d232 --- /dev/null +++ b/faq/items/bond-rewards-3.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqChainName, FaqFrameDuration, FaqLink } from 'shared/components'; + +export const BondRewards3: Faq = { + title: 'Why didn’t I get rewards?', + anchor: 'why-didnt-i-get-rewards', + content: ( +
+

+ If your validator's performance was below the threshold within the + CSM Performance Oracle frame ( for ) + the validator does not receive rewards for the given frame. Read more + about{' '} + + the CSM Performance Oracle + + . +

+
+ ), +}; diff --git a/faq/items/bond-rewards-4.tsx b/faq/items/bond-rewards-4.tsx new file mode 100644 index 000000000..e38de44e5 --- /dev/null +++ b/faq/items/bond-rewards-4.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const BondRewards4: Faq = { + title: 'Why add a bond?', + anchor: 'why-add-a-bond', + content: ( +
+

+ Submitting a bond serves as a risk mitigation measure for both the + Ethereum network and the Lido protocol. +

+

+ There are several major reasons for a CSM Node Operator's bond to + be penalized, including: +

+
    +
  • + The operator has stolen EL rewards (MEV).{' '} + Penalty amount = amount stolen + fixed stealing fine; +
  • +
  • + + The validator's withdrawal balance is less than 32 ETH + + .{' '} + Penalty amount = 32 - validator's withdrawal balance + ; +
  • +
  • + The operator has not exited the validators in time.{' '} + Penalty amount = exitDelayPenalty (a fixed amount set by + the DAO); +
  • +
  • + + The validator has been ejected via{' '} + + EIP-7002 + {' '} + due to an excessive number of strikes. + {' '} + Penalty amount = badPerformancePenalty (a fixed amount + set by the DAO); +
  • +
  • + + Force ejection via{' '} + + EIP-7002 + {' '} + was triggered for the validator. + {' '} + Penalty amount ={' '} + min(actual TW fee paid, maxWithdrawalRequestFee). +
  • +
+
+ ), +}; diff --git a/faq/items/bond-rewards-5.tsx b/faq/items/bond-rewards-5.tsx new file mode 100644 index 000000000..98ec485a2 --- /dev/null +++ b/faq/items/bond-rewards-5.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const BondRewards5: Faq = { + title: 'How to claim ETH using a withdrawal NFT', + anchor: 'how-to-claim-eth-using-a-withdrawal-nft', + content: ( +
+

+ Claiming bond and rewards in a form of ETH constitutes an stETH + withdrawal process (unstake).{' '} +

+

The withdrawal process consists of several steps you need to do:

+
    +
  • + Submit a withdrawal request by choosing ETH as a + token for bond/rewards claim. As a result of this step, you will + receive a withdrawal NFT.{' '} +
  • +
  • + Claim your ETH after request fulfilment. The + fulfilment process takes 1-5 days (or longer),{' '} + + depending on a variety of factors + + . To know if your ETH is ready to be claimed you, can check its status + on the{' '} + + Claim page + + . If your request is marked as "Ready to claim + ", it is time for you to get your ETH back. +
  • +
+

+ For more information about withdrawals,{' '} + + follow the page + + . +

+
+ ), +}; diff --git a/faq/items/index.ts b/faq/items/index.ts new file mode 100644 index 000000000..fb53804f5 --- /dev/null +++ b/faq/items/index.ts @@ -0,0 +1,43 @@ +export * from './bond-rewards-1'; +export * from './bond-rewards-2'; +export * from './bond-rewards-3'; +export * from './bond-rewards-4'; +export * from './bond-rewards-5'; +export * from './keys-1'; +export * from './keys-10'; +export * from './keys-11'; +export * from './keys-12'; +export * from './keys-13'; +export * from './keys-14'; +export * from './keys-15'; +export * from './keys-2'; +export * from './keys-3'; +export * from './keys-4'; +export * from './keys-5'; +export * from './keys-6'; +export * from './keys-7'; +export * from './keys-8'; +export * from './keys-9'; +export * from './locked-bond-1'; +export * from './locked-bond-2'; +export * from './locked-bond-3'; +export * from './main-1'; +export * from './main-2'; +export * from './main-3'; +export * from './main-4'; +export * from './main-5'; +export * from './main-6'; +export * from './main-7'; +export * from './main-8'; +export * from './monitoring-1'; +export * from './monitoring-2'; +export * from './monitoring-3'; +export * from './monitoring-4'; +export * from './monitoring-5'; +export * from './operator-type-1'; +export * from './operator-type-2'; +export * from './roles-1'; +export * from './roles-2'; +export * from './roles-3'; +export * from './roles-4'; +export * from './roles-5'; diff --git a/faq/items/keys-1.tsx b/faq/items/keys-1.tsx new file mode 100644 index 000000000..e271c37f8 --- /dev/null +++ b/faq/items/keys-1.tsx @@ -0,0 +1,110 @@ +import React from 'react'; +import { Faq } from 'types'; +import { + FaqChainName, + FaqLidoRewardsVault, + FaqLink, + FaqOnlyMainnet, + FaqOnlyTestnet, + FaqWithdrawalVault, +} from 'shared/components'; + +export const Keys1: Faq = { + title: ( + <> + How to set up a validator for CSM ? + + ), + anchor: 'how-to-set-up-a-validator', + content: ( +
+

+ A detailed guide on preparing all the validation tools for CSM can be + found{' '} + + here + + . +

+

+ A shorter flow of setting up a CSM validator for looks + as follows:{' '} +

+
    +
  1. + + Generate new validator keys + {' '} + setting the withdrawal_address to the Lido Withdrawal + Vault on{' '} + + : + {' '} + , specify the deposit amount of 32 ETH, and set + WC type to 0x01 (do NOT make a deposit) +
  2. +
  3. + + Configure your validator client + {' '} + (and/or beacon node) setting the fee_recipient flag to + the designated fee recipient address (Lido Execution Layer Rewards + Vault) on{' '} + + : + {' '} + and import the newly generated CSM keystores +
  4. + +
  5. + + Configure your MEV-Boost service + + . Do not set the `min-bid` flag (or set 0) and set the `relay` flags + only to{' '} + + the list of designated MEV relays for Lido CSM on + +
  6. +
    + +
  7. + + Configure your MEV-Boost service + + . Min-bid may be configured either at MEV-Boost level + or at the CL client, the current acceptable maximum value for + min-bid is 0.07{' '} + + based on community consensus + {' '} + and may change. Builder-boost-factor should be set to + 100%, i.e. local and builder payloads should be treated with equal + weights. The relay flags should be set to a list of + values only using relays from{' '} + + the list of Vetted MEV-Boost Relays for Lido CSM + + . Note that at least one “must use” relay should be used. Relays not + mentioned in the list are not allowed for use +
  8. +
    +
  9. + + Upload the newly generated deposit data + {' '} + file pertaining to your CSM keystores onto{' '} + the Lido CSM Widget and + provide the required bond amount in ETH/stETH/wstETH. Before + uploading, make sure that nodes are synced, running, and corresponding + keystores are imported. Hence, your setup is ready for the validator + activation +
  10. +
  11. + Wait for your CSM validator keys to be deposited through the protocol + and make sure your node remains online in the meantime! +
  12. +
+
+ ), +}; diff --git a/faq/items/keys-10.tsx b/faq/items/keys-10.tsx new file mode 100644 index 000000000..532697056 --- /dev/null +++ b/faq/items/keys-10.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Keys10: Faq = { + title: + 'What is the difference between removing, exiting, and ejecting a key?', + anchor: 'what-is-the-difference-between-removing-exiting-and-ejecting-a-key', + content: ( +
+

+ Removing a key is an operation when the validator key is removed from + the Node Operator on-chain keys storage in CSM. Only non-deposited keys + can be removed. Due to associated queue maintenance costs{' '} + keyRemovalCharge is charged from the Node Operator's + bond for each removed key. +

+

+ Exiting a key (validator) is an operation when the Node Operator + publishes a voluntary exit message associated with the corresponding + active validator to the Beacon chain. Once published, the exit process + will be started for the validator. Note that only activated validators + might be exited. Also, a period of 256 epochs (approx. 27 + hours) should pass since the validator activation before the voluntary + exit message can be published. +

+

+ Ejecting the key (validator) is an operation when the validator exit is + initiated from the validator's withdrawal credentials on Execution + layer. Since all validators in CSM have their withdrawal credentials set + to Lido Withdrawal Vault, the process can only be initiated from this + smart contract. CSM provides a proxy method for the Node Operators to + voluntary eject their validators if they decide to do so. In this case, + the Node Operator is responsible for attaching a corresponding payment + to cover{' '} + TW fee + . Also, ejection can be invoked from the Lido protocol side in the + following cases: +

+
    +
  • + The validator has excessive number of performance strikes assigned; +
  • +
  • + The validator was requested to exit by VEBO but have not exited in + time; +
  • +
  • Based on the Lido DAO decision;
  • +
+
+ ), +}; diff --git a/faq/items/keys-11.tsx b/faq/items/keys-11.tsx new file mode 100644 index 000000000..3bf6214c3 --- /dev/null +++ b/faq/items/keys-11.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Keys11: Faq = { + title: 'When does a validator become withdrawn?', + anchor: 'when-does-a-validator-become-withdrawn', + content: ( +
+

+ On the Ethereum network, a validator can be withdrawn after + successfully exiting from the consensus layer, but the exact timing of + withdrawal depends on several factors related to Ethereum protocol + mechanics: +

+
    +
  1. + Exit Queue: When a validator initiates an exit, it + enters an exit queue. The time required to exit + depends on the number of validators exiting +  and the churn limit (the number of + validators allowed to exit or enter per epoch). +
  2. +
  3. + Withdrawal Process: After exiting the active + validator set, the validator enters a  + withdrawable state. This state is determined by + the withdrawable epoch, which is set to the exit + epoch + a minimum delay of 256 epochs (~27 + hours). +
  4. +
  5. + Finalization of Withdrawal: Once the withdrawable + epoch is reached, the validator balance will be transferred to the + validator's withdrawal credentials (in the case of the Lido + protocol, the Lido Withdrawal Vault) within the next iteration of the + Consensus Layer withdrawal sweep cycle. How long this takes depends on + the validator's position in the overall sweep cycle, and time + difference between the withdrawable epoch and when its turn will come + to be swept. Once the withdrawal has occurred, the fact of the + withdrawal can be reported to CSM permissionlessly. Once that occurs, + the part of the Node Operator's bond used for this validator is + released. At this point, the Node Operator can claim the bond on the{' '} + Bond & Rewards Claim tab. +
  6. +
+
+ ), +}; diff --git a/faq/items/keys-12.tsx b/faq/items/keys-12.tsx new file mode 100644 index 000000000..132af0a28 --- /dev/null +++ b/faq/items/keys-12.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Keys12: Faq = { + title: 'Why a key can get ejected?', + anchor: 'why-a-key-can-get-ejected', + content: ( +
+

+ Validator ejection can be invoked from the Lido protocol side in the + following cases: +

+
    +
  • + The validator has excessive number of performance strikes assigned; +
  • +
  • + The validator was requested to exit by VEBO but have not exited in + time; +
  • +
  • Based on the Lido DAO decision;
  • +
+

+ Also, Node Operators can voluntary eject their validators if they decide + to so. In this case, the Node Operator is responsible for attaching a + corresponding payment to cover{' '} + TW fee + . +

+
+ ), +}; diff --git a/faq/items/keys-13.tsx b/faq/items/keys-13.tsx new file mode 100644 index 000000000..64d7b73ec --- /dev/null +++ b/faq/items/keys-13.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { FaqShareLimit } from 'shared/components'; +import { Faq } from 'types'; + +export const Keys13: Faq = { + title: 'What is the CSM Stake Share Limit?', + anchor: 'what-is-the-csm-stake-share-limit', + content: ( +
+

+ The stake share limit is a parameter defined for each Staking Module + based on its risk profile. It determines the percentage of the total + stake in the Lido Protocol that can be allocated to the module. + Currently, the stake share limit for CSM is set at . + Once CSM reaches its stake share limit, new keys can still be uploaded, + but deposits to these keys may take a very long time (e.g. months), if + they are deposited to at all. These factors affect the possibility of + new deposits to your uploaded keys: +

+
    +
  • + The number of keys already in the deposit queue, and the position of + your keys in this queue +
  • +
  • The number of keys that will exit from CSM
  • +
  • + Changes in the total volume of stake in the Lido Protocol (both net + flows as well as whether overall Lido protocol stake increases or not) +
  • +
+

+ In other words, if keys had not been deposited to before CSM reached its + limit, they may still be deposited to later if: +

+
    +
  • The overall stake volume in the Lido Protocol increases
  • +
  • Keys exit from CSM, freeing up space for new keys
  • +
  • The DAO decides to increase CSM's stake share limit
  • +
+

+ While keys are awaiting deposit, Node Operators continue to receive + daily bond rewards based on the bond they submitted. However, they do + not receive Node Operator rewards, as the keys remain inactive until + they are fully deposited. +

+
+ ), +}; diff --git a/faq/items/keys-14.tsx b/faq/items/keys-14.tsx new file mode 100644 index 000000000..49b643317 --- /dev/null +++ b/faq/items/keys-14.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Keys14: Faq = { + title: 'What is a referrer?', + anchor: 'what-is-a-referrer', + showRules: ['HAS_REFERRER'], + content: ( +
+

+ A referrer is a software provider specializing in node/validator setup + that integrated CSM into their tools. When a referrer directs solo + stakers to join CSM via its tool, these Node Operators are marked as + being referred from this provider. It doesn't affect the Node + Operators rewards in any way and is used just for the funnel-tracking + purposes. +

+
+ ), +}; diff --git a/faq/items/keys-15.tsx b/faq/items/keys-15.tsx new file mode 100644 index 000000000..fe8d0b329 --- /dev/null +++ b/faq/items/keys-15.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqDiscordChannel, FaqLink } from 'shared/components'; + +export const Keys15: Faq = { + title: 'What to do in case of technical issues?', + anchor: 'what-to-do-in-case-of-technical-issues', + content: ( +
+

+ For community assistance, join the " + + " channel on the{' '} + + Lido Discord server + {' '} + to seek advice and guidance. +

+
+ ), +}; diff --git a/faq/items/keys-2.tsx b/faq/items/keys-2.tsx new file mode 100644 index 000000000..d8e75d42e --- /dev/null +++ b/faq/items/keys-2.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Keys2: Faq = { + title: 'Why upload a bond?', + anchor: 'why-upload-a-bond', + content: ( +
+

+ Submitting a bond serves as a risk mitigation measure for both the + Ethereum network and the Lido protocol. +

+

+ There are several major reasons for a CSM Node Operator's bond to + be penalized, including: +

+
    +
  • + The operator has stolen EL rewards (MEV).{' '} + Penalty amount = amount stolen + fixed stealing fine; +
  • +
  • + + The validator's withdrawal balance is less than 32 ETH + + .{' '} + Penalty amount = 32 - validator's withdrawal balance + ; +
  • +
  • + The operator has not exited the validators in time.{' '} + Penalty amount = exitDelayPenalty (a fixed amount set by + the DAO); +
  • +
  • + + The validator has been ejected via{' '} + + EIP-7002 + {' '} + due to an excessive number of strikes. + {' '} + Penalty amount = badPerformancePenalty (a fixed amount + set by the DAO); +
  • +
  • + + Force ejection via{' '} + + EIP-7002 + {' '} + was triggered for the validator. + {' '} + Penalty amount ={' '} + min(actual TW fee paid, maxWithdrawalRequestFee). +
  • +
+
+ ), +}; diff --git a/faq/items/keys-3.tsx b/faq/items/keys-3.tsx new file mode 100644 index 000000000..982927c96 --- /dev/null +++ b/faq/items/keys-3.tsx @@ -0,0 +1,28 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { FaqBondAmount, FaqChainName, FaqCurveImage } from 'shared/components'; +import { Faq } from 'types'; + +export const Keys3: Faq = { + title: 'How much bond is needed?', + anchor: 'how-much-bond-is-needed', + content: ( +
+

+ The initial bond requirement for the first validator for the{' '} + is . + However, for Identified Community Stakers (ICS), this amount is reduced + to to incentivize + independent stakers participation. +

+

+ The amount for the second and subsequent validators is{' '} + +

+

+ For the , the values for the bond curve are the + following: +

+ +
+ ), +}; diff --git a/faq/items/keys-4.tsx b/faq/items/keys-4.tsx new file mode 100644 index 000000000..6fdf2e2cc --- /dev/null +++ b/faq/items/keys-4.tsx @@ -0,0 +1,25 @@ +import { FaqChainName, FaqCurveImage, FaqLink } from 'shared/components'; +import { Faq } from 'types'; + +export const Keys4: Faq = { + title: 'What is the bond curve?', + anchor: 'what-is-the-bond-curve', + content: ( +
+

+ + The bond curve + {' '} + is a function that determines the amount of bond required for each + subsequent validator operated by the node operator. For Identified + Community Stakers (ICS), a unique bond curve function is applied to + independent stakers participation. +

+

+ For the , the values for the bond curve are the + following: +

+ +
+ ), +}; diff --git a/faq/items/keys-5.tsx b/faq/items/keys-5.tsx new file mode 100644 index 000000000..82fad5219 --- /dev/null +++ b/faq/items/keys-5.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Keys5: Faq = { + title: 'Difference between bond types (ETH, stETH, wstETH)?', + anchor: 'difference-between-bond-types-eth-steth-wsteth', + content: ( +
+

+ Bonds are stored in the form of stETH to so that participation as a Node + Operator is more capital efficient than if the bond were un-staked (or + could only be staked if sufficient deposits to fill the submitted + validators were present). While node operators can submit bond in ETH, + stETH, or wstETH, any token other than stETH is converted to stETH for + consistency in bond format. +

+
+ ), +}; diff --git a/faq/items/keys-6.tsx b/faq/items/keys-6.tsx new file mode 100644 index 000000000..5d092637a --- /dev/null +++ b/faq/items/keys-6.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Keys6: Faq = { + title: 'When does a validator become active?', + anchor: 'when-does-a-validator-become-active', + content: ( +
+

+ After key submission, and if keys have been successfully validated, two + actions are required for a validator to be activated: +

+
    +
  1. + Deposit by Lido Protocol: The time to deposit a + validator is unpredictable and depends on factors such as total stake + inflows and outflows, gas considerations, module shares, CSM deposit + queue size, and the Node Operator's place in the queue. +
  2. +
  3. + Activation on Ethereum Network: Once deposited, the + validator enters the Beacon Chain activation queue. The time to + activation depends on the total number of validators in the queue + awaiting activation and the rate of queue processing, which varies + based on the total number of active Ethereum validators. +
  4. +
+
+ ), +}; diff --git a/faq/items/keys-7.tsx b/faq/items/keys-7.tsx new file mode 100644 index 000000000..6f57921d3 --- /dev/null +++ b/faq/items/keys-7.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { FaqKeyRemovalFee } from 'shared/components'; +import { Faq } from 'types'; + +export const Keys7: Faq = { + title: 'Why pay for key deletion?', + anchor: 'why-pay-for-key-deletion', + content: ( +
+

+ Key deletion incurs a removal fee of , which is + deducted from the Node Operator's bond per each deleted key to + cover the maximal possible operational costs associated with the queue + processing. This fee is intended to protect the module from potential + DoS attacks by malicious actors who could clog the queue with empty + slots by adding and removing keys, and covers the maximal possible + operational costs associated with the queue processing. The fee + discourages misuse, keeping the system clear of invalid keys or keys + that don't end up being deposited to. +

+
+ ), +}; diff --git a/faq/items/keys-8.tsx b/faq/items/keys-8.tsx new file mode 100644 index 000000000..509bcd24e --- /dev/null +++ b/faq/items/keys-8.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Keys8: Faq = { + title: "Can't see the key for deletion?", + anchor: 'cant-see-the-key-for-deletion', + content: ( +
+

+ Only keys that have not been deposited yet can be deleted. If a key has + already been deposited, you can either{' '} + + exit the validator on the Consensus Layer (CL) + {' '} + or use the triggerable withdrawals mechanism to eject your validator + (can be done on the "Keys" → "Delete" → + "Eject" tab). Once withdrawn, the node operator can claim the + excess bond. +

+
+ ), +}; diff --git a/faq/items/keys-9.tsx b/faq/items/keys-9.tsx new file mode 100644 index 000000000..080f669b8 --- /dev/null +++ b/faq/items/keys-9.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Keys9: Faq = { + title: 'How to stop validating in CSM?', + anchor: 'how-to-stop-validating-in-csm', + content: ( +
+

+ Exiting CSM validator keys works the same way as exiting solo staking + validator keys. The guide on how to exit the validator can be found{' '} + + here + + . +

+
+ ), +}; diff --git a/faq/items/locked-bond-1.tsx b/faq/items/locked-bond-1.tsx new file mode 100644 index 000000000..4fa99b6fe --- /dev/null +++ b/faq/items/locked-bond-1.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const LockedBond1: Faq = { + title: 'Why is the bond locked?', + anchor: 'why-is-the-bond-locked', + content: ( +
+

+ Bond may be locked in the case of delayed penalties, typically for MEV + stealing event reported by a dedicated committee. This measure ensures + that node operators are held accountable for any misbehavior or rule + violations. +

+
+ ), +}; diff --git a/faq/items/locked-bond-2.tsx b/faq/items/locked-bond-2.tsx new file mode 100644 index 000000000..07377b803 --- /dev/null +++ b/faq/items/locked-bond-2.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const LockedBond2: Faq = { + title: 'How to unlock the bond?', + anchor: 'how-to-unlock-the-bond', + content: ( +
+

+ To unlock the bond, the penalty amount, which includes the stolen amount + and a fixed stealing fine, must be compensated on the "Locked + bond" tab. This action can be performed from the Manager Address of + the Node Operator.{' '} +

+

+ If there are disputes regarding the penalty, node operators can start a + public discussion about the penalty applied on the Lido research forum + under the{' '} + + CSM Support + {' '} + category. +

+
+ ), +}; diff --git a/faq/items/locked-bond-3.tsx b/faq/items/locked-bond-3.tsx new file mode 100644 index 000000000..c01975518 --- /dev/null +++ b/faq/items/locked-bond-3.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const LockedBond3: Faq = { + title: 'Consequences of not compensating?', + anchor: 'consequences-of-not-compensating', + content: ( +
+

+ In case of refusal to compensate the penalty, a protocol rule violation + occurs which results in the reset of all node operator benefits. The + locked bond is burned to compensate all stETH holders for the rewards + stolen. +

+
+ ), +}; diff --git a/faq/items/main-1.tsx b/faq/items/main-1.tsx new file mode 100644 index 000000000..757d8d613 --- /dev/null +++ b/faq/items/main-1.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Main1: Faq = { + title: 'Why run an Ethereum validator?', + anchor: 'why-run-an-ethereum-validator', + content: ( +
+

Running an Ethereum validator allows one to:

+
    +
  1. + Receive Staking Rewards: Validators get network + rewards for performing their duties on the Ethereum blockchain (note: + incorrectly or not performing duties incurs penalties).{' '} +
  2. +
  3. + Support the Network: By running a validator, you + actively contribute to the decentralization and security of the + Ethereum network. Validators play a crucial role in reaching consensus + and validating transactions, which enhances the network's + reliability and resilience. +
  4. +
  5. + Learn and Engage with the community: Operating a + validator node provides valuable insights into blockchain technology + and consensus mechanisms. Through hands-on experience, individuals can + deepen their understanding of Ethereum's inner workings. + Moreover, it provides an opportunity to engage with the Ethereum + community, share knowledge, and contribute to the network's + development. +
  6. +
+
+ ), +}; diff --git a/faq/items/main-2.tsx b/faq/items/main-2.tsx new file mode 100644 index 000000000..76bfd45e3 --- /dev/null +++ b/faq/items/main-2.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Main2: Faq = { + title: 'What is required to be a Node Operator in CSM?', + anchor: 'what-is-required-to-be-a-node-operator-in-csm', + content: ( +
+

+ Node operation in CSM involves a long-term commitment to Ethereum's + decentralization. Responsibilities include: +

+
    +
  • + Hardware Setup: Setting up a computer that meets the + system requirements for running validator nodes. +
  • +
  • + Configuration: Properly configuring nodes and + validators, ensuring they are in sync with the Ethereum blockchain and + other network participants. +
  • +
  • + Security Measures: Implementing robust security + measures to safeguard against external threats and internal + vulnerabilities. +
  • +
  • + Maintenance: Sustaining ongoing maintenance + throughout the validator's lifespan, which involves monitoring + performance, troubleshooting issues, and applying necessary updates. +
  • +
+
+ ), +}; diff --git a/faq/items/main-3.tsx b/faq/items/main-3.tsx new file mode 100644 index 000000000..79d0f42e1 --- /dev/null +++ b/faq/items/main-3.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Main3: Faq = { + title: 'What do node operators receive in CSM?', + anchor: 'what-do-node-operators-receive-in-csm', + content: ( +
+

Node operators benefit from:

+
    +
  • + Daily Bond Rebase: The collateral for CSM NOs is + eligible for{' '} + + rewards through stETH's rebase + + , even before validator activation.{' '} +
  • +
  • + Socialized Rewards: Rewards are smoothed across the + largest validator set, mitigating volatility. This means that even in + the event of small outages or disruptions, node operators can still + receive rewards, reducing the risk of rewards loss. +
  • +
+
+ ), +}; diff --git a/faq/items/main-4.tsx b/faq/items/main-4.tsx new file mode 100644 index 000000000..b19efa9a0 --- /dev/null +++ b/faq/items/main-4.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Main4: Faq = { + title: 'What are the risks of running a validator?', + anchor: 'what-are-the-risks-of-running-a-validator', + content: ( +
+

Node operators face several risks, including:

+
    +
  1. + Technical Risk: Maintaining reliable and secure + hardware and software setups is essential. Any technical failure or + vulnerability in the validator setup could lead to penalties. +
  2. +
  3. + Penalties for Misbehavior: Validators can be + penalized for various reasons, such as going offline or attempting to + manipulate the network. +
  4. +
  5. + Market Risk: The value of ETH can fluctuate + significantly, impacting the value of the validator's staked ETH. +
  6. +
  7. + Network Risk: Validators are part of a decentralized + network, and the security and stability of the Ethereum network as a + whole can affect individual validators. Events such as network attacks + or protocol upgrades may impact validator operations, leading to + potential disruptions or losses. +
  8. +
  9. + Operational Risk: Validators require ongoing + maintenance and monitoring to ensure smooth operation. Any operational + issues, such as hardware failures or connectivity issues, could + disrupt validator performance and result in rewards losses. +
  10. +
  11. + Slashing Risk: Validators can be slashed, meaning + they lose a portion of their staked ETH, for violating network rules + or behaving maliciously. Slashing can occur due to actions such as + double signing or failing to validate correctly, resulting in + significant penalties. +
  12. +
+
+ ), +}; diff --git a/faq/items/main-5.tsx b/faq/items/main-5.tsx new file mode 100644 index 000000000..446ac278e --- /dev/null +++ b/faq/items/main-5.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Main5: Faq = { + title: 'How does CSM work?', + anchor: 'how-does-csm-work', + content: ( +
+

+ Refer to{' '} + + the CSM page + {' '} + for a more detailed explanation of its mechanics and functionalities. +

+
+ ), +}; diff --git a/faq/items/main-6.tsx b/faq/items/main-6.tsx new file mode 100644 index 000000000..63699866d --- /dev/null +++ b/faq/items/main-6.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Main6: Faq = { + title: 'What makes CSM unique?', + anchor: 'what-makes-csm-unique', + content: ( +
+

+ CSM provides several unique features to attract and benefit community + stakers: +

+
    +
  • + Rewards Smoothing: Rewards, including Execution Layer + (EL) rewards and MEV, are smoothed with other modules to provide more + stable rewards comparable to operating validators solo. +
  • +
  • + Low Bond Requirement: A low bond for node operators + makes participation more accessible to a broader range of prospective + operators. +
  • +
  • + Exclusive Use of ETH (stETH): CSM exclusively uses + ETH ((w)stETH) for bond and rewards, eliminating the need for other + assets and simplifying the process for node operators. The bond can be + submitted as ETH, wstETH, or stETH, and both bond and rewards can be + withdrawn in any of the three forms (withdrawals in the form of ETH + follow the{' '} + + normal Lido on Ethereum unstaking process + + ). +
  • +
  • + Enhanced User Experience: Accessible through a + multitude of options -- from a web UI to integrations with Dappnode, + Stereum, Eth-Docker, Sedge, Stereum, CoinPillar, etc., CSM offers a + leading user-friendly experience, with reduced gas fees for on-chain + operations and simplified transactions for joining and claiming + rewards. +
  • +
  • + Higher Reward Potential: Node operators are + potentially able to earn more rewards compared to vanilla solo + staking, making CSM an attractive option for operators looking to run + more validators to earn rewards. +
  • +
+
+ ), +}; diff --git a/faq/items/main-7.tsx b/faq/items/main-7.tsx new file mode 100644 index 000000000..72caa7774 --- /dev/null +++ b/faq/items/main-7.tsx @@ -0,0 +1,29 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import React from 'react'; +import { FaqBondAmount, FaqChainName, FaqCurveImage } from 'shared/components'; +import { Faq } from 'types'; + +export const Main7: Faq = { + title: 'How much bond is needed?', + anchor: 'how-much-bond-is-needed', + content: ( +
+

+ The initial bond requirement for the first validator for the{' '} + is . + However, for Identified Community Stakers (ICS), this amount is reduced + to to incentivize + independent stakers participation. +

+

+ The amount for the second and subsequent validators is{' '} + +

+

+ For the , the values for the bond curve are the + following: +

+ +
+ ), +}; diff --git a/faq/items/main-8.tsx b/faq/items/main-8.tsx new file mode 100644 index 000000000..0abd42834 --- /dev/null +++ b/faq/items/main-8.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqDiscordChannel, FaqLink } from 'shared/components'; + +export const Main8: Faq = { + title: 'How can I get help?', + anchor: 'how-can-i-get-help', + content: ( +
+

+ For community assistance, join the " + + " channel on the{' '} + + Lido Discord server + {' '} + to seek advice and guidance. +

+
+ ), +}; diff --git a/faq/items/monitoring-1.tsx b/faq/items/monitoring-1.tsx new file mode 100644 index 000000000..e3ee5de15 --- /dev/null +++ b/faq/items/monitoring-1.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { FaqPerformanceLeeway } from 'shared/components/faq/faq-performance-leeway'; +import { Faq } from 'types'; + +export const Monitoring1: Faq = { + title: 'What is the performance threshold?', + anchor: 'what-is-the-performance-threshold', + content: ( +
+

+ The performance threshold is a relative variable determined as follows: +

+

+ + CSM Performance threshold (%) = Average validator performance across + the whole Ethereum network (%) - + +

+

+ A performance threshold is utilized to determine the allocation of the + actual Node Operator rewards. Validators with performance above the + threshold are included in the allocation pool, while the rest are not.{' '} +

+
+ ), +}; diff --git a/faq/items/monitoring-2.tsx b/faq/items/monitoring-2.tsx new file mode 100644 index 000000000..3b41da276 --- /dev/null +++ b/faq/items/monitoring-2.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqFrameDuration, FaqLink } from 'shared/components'; + +export const Monitoring2: Faq = { + title: 'How does the CSM Performance Oracle work?', + anchor: 'how-does-the-csm-performance-oracle-work', + content: ( +
+

+ The Performance Oracle calculates validators performance based on + their attestation, block proposal, + and sync committee participation effectiveness. The + exact formulas for performance calculation can be found  + + here + + . The Performance Oracle compares the performance of each validator with + the performance threshold to determine whether the validator should or + should not be included in the rewards distribution during the frame. +

+

+ The frame for the Performance Oracle report + is set to . The Performance Oracle creates a  + + Merkle tree + +  with the allocation of the Node Operator rewards and delivers the + root on-chain. To make the original tree available to users, it is + published on IPFS +  and  + + GitHub + + .{' '} +

+
+ ), +}; diff --git a/faq/items/monitoring-3.tsx b/faq/items/monitoring-3.tsx new file mode 100644 index 000000000..d6d742b01 --- /dev/null +++ b/faq/items/monitoring-3.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Monitoring3: Faq = { + title: 'What is a strike?', + anchor: 'what-is-a-strike', + content: ( +
+

+ A strike is an indicator of the validator performing below the + performance threshold in the given frame. Strikes have a lifetime — a + time after which the strike is no longer considered valid and gets + removed form the strikes{' '} + + Merkle tree + {' '} + delivered by the Performance Oracle. +

+
+ ), +}; diff --git a/faq/items/monitoring-4.tsx b/faq/items/monitoring-4.tsx new file mode 100644 index 000000000..a46ead007 --- /dev/null +++ b/faq/items/monitoring-4.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Monitoring4: Faq = { + title: 'How are the strikes assigned?', + anchor: 'how-are-the-strikes-assigned', + content: ( +
+

+ Strikes are assigned on per-validator basis. If the validator's + performance within a Performance Oracle frame is below the threshold, a + strike will be assigned and reported on-chain by the Performance Oracle + using{' '} + + Merkle tree + + . +

+
+ ), +}; diff --git a/faq/items/monitoring-5.tsx b/faq/items/monitoring-5.tsx new file mode 100644 index 000000000..38836c56f --- /dev/null +++ b/faq/items/monitoring-5.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Monitoring5: Faq = { + title: 'What to do in case of a strike assigned?', + anchor: 'what-to-do-in-case-of-a-strike-assigned', + content: ( +
+

+ Since a strike is an indicator of the validator performing below the + performance threshold in the given frame, Node Operators should improve + their validator's performance to avoid getting additional strikes. + If the validator gets more than strikesThreshold strikes + assigned, it will be ejected using{' '} + + EIP-7002 + + . In case of ejection both badPerformancePenalty and{' '} + min(actual TW fee paid, maxWithdrawalRequestFee)will be + confiscated from the Node Operator's bond upon validator withdrawal + reporting.{' '} +

+

+ If Node Operators are unable to maintain validator's performance + above the performance threshold they should voluntary exit their + validators immediately to avoid damaging overall protocol's + performance and application of the corresponding penalties. +

+
+ ), +}; diff --git a/faq/items/operator-type-1.tsx b/faq/items/operator-type-1.tsx new file mode 100644 index 000000000..24bf790ef --- /dev/null +++ b/faq/items/operator-type-1.tsx @@ -0,0 +1,82 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const OperatorType1: Faq = { + title: 'What is a Node Operator type?', + anchor: 'what-is-a-node-operator-type', + content: ( +
+

+ Node Operator type is a set of custom parameters values for a Node + Operator in CSM. Node Operator type is determined based on the Node + Operator's bond curve. The full list of parameters for the Node + Operator is: +

+
    +
  • + keyRemovalCharge - a fee charged for each deleted + deposit data record; +
  • +
  • + elRewardsStealingAdditionalFine - an additional fine + charged for each validator that has stolen EL rewards; +
  • +
  • + keysLimit - a limit on the number of active keys for + the Node Operator; +
  • +
  • + queuePriority and maxDeposits +  - parameters defining the priority queue for the Node Operator; +
  • +
  • + rewardShare - a share of the Node Operator rewards + that the Node Operator receives for each validator. Can be customized + depending on the key index in the Node Operator's keys storage; +
  • +
  • + performanceLeeway - a leeway for the Node + Operator's validator's performance, which is used to define + a performance threshold. Can be customized depending on the key index + in the Node Operator's keys storage; +
  • +
  • + strikesParams - parameters defining the Node + Operator's strikes system, which is used to decide on the Node + Operator's validator's ejection due to systematic bad + performance; +
  • +
  • + badPerformancePenalty - a penalty charged for each + validator that has been ejected due to bad performance; +
  • +
  • + performanceCoefficients - coefficients used to + calculate the Node Operator's performance based on the + validator's effectiveness in performing duties like attestation, + proposing blocks, and sync committee participation; +
  • +
  • + allowedExitDelay - an allowed delay between the + moment Node Operator's validator was requested to exit and the + moment it is actually initiated exit process; +
  • +
  • + exitDelayPenalty - a penalty charged for each + validator that has been requested to exit but has not exited within + the allowed delay; +
  • +
  • + maxWithdrawalRequestFee - a maximum fee charged for + each Node Operator's validator that has been forcefully ejected + using  + + EIP-7002 + + ; +
  • +
+
+ ), +}; diff --git a/faq/items/operator-type-2.tsx b/faq/items/operator-type-2.tsx new file mode 100644 index 000000000..91fac3172 --- /dev/null +++ b/faq/items/operator-type-2.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const OperatorType2: Faq = { + title: 'What operator types exist?', + anchor: 'what-operator-types-exist', + content: ( +
+

Currently there are three Node Operator types:

+
    +
  • + Default operator - the default Node Operator type assigned to all new + Node Operators joining CSM via the Default Gate; +
  • +
  • + Identified Community Staker - the custom Node Operator type assigned + to the new Node Operators joining via the Identified Community Stakers + Gate. This type can also be claimed by the Node Operators who have + passed the identification process after joining CSM via the Default + Gate; +
  • +
  • + Identified DVT Clusters (IDVTC) - the custom Node Operator type + designed for DVT Clusters and creates a more capital-efficient path + for independent stakers who are willing to identify themselves and + operate validators collaboratively via DVT. This approach combines the + trust properties of ICS with the operational resilience of DVT, + aligning incentives for small independent operators who share + validator rewards within a cluster. +
  • +
+
+ ), +}; diff --git a/faq/items/roles-1.tsx b/faq/items/roles-1.tsx new file mode 100644 index 000000000..e9ea16215 --- /dev/null +++ b/faq/items/roles-1.tsx @@ -0,0 +1,32 @@ +import { ROLES } from '@lidofinance/lido-csm-sdk'; +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink, RoleActionsList } from 'shared/components'; + +export const Roles1: Faq = { + title: 'What are rewards and manager addresses?', + anchor: 'what-are-rewards-and-manager-addresses', + content: ( +
+

+ There are two addresses associated with your Node Operator that have + different scope of responsibilities for managing your Node Operator.{' '} +

+ + +

+ Read more about addresses management{' '} + + here + + . +

+
+ ), +}; diff --git a/faq/items/roles-2.tsx b/faq/items/roles-2.tsx new file mode 100644 index 000000000..8c4f916ec --- /dev/null +++ b/faq/items/roles-2.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Faq } from 'types'; +import { FaqLink } from 'shared/components'; + +export const Roles2: Faq = { + title: 'Why should these addresses be different?', + anchor: 'why-should-these-addresses-be-different', + content: ( +
+

+ It's recommended to use different addresses for security reasons. + For example, a hot wallet may be used for the Manager Address to + simplify daily operations, while a cold wallet (or something like a + Safe) is preferable for the Rewards Address to enhance security.{' '} +

+

+ Read more about addresses management{' '} + + here + + . +

+
+ ), +}; diff --git a/faq/items/roles-3.tsx b/faq/items/roles-3.tsx new file mode 100644 index 000000000..000a801e2 --- /dev/null +++ b/faq/items/roles-3.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Roles3: Faq = { + title: 'How to accept a change in address request?', + anchor: 'how-to-accept-a-change-in-address-request', + content: ( +
+

+ To accept a change in address request, connect to the CSM widget with + the new address, navigate to the "Roles" → "Inbox + requests" tab, select and accept the request, and confirm the + transaction in your wallet. Changes are made once the transaction is + processed. +

+
+ ), +}; diff --git a/faq/items/roles-4.tsx b/faq/items/roles-4.tsx new file mode 100644 index 000000000..7e5aef553 --- /dev/null +++ b/faq/items/roles-4.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Roles4: Faq = { + title: 'What to do if the change is submitted to a wrong address?', + anchor: 'what-to-do-if-the-change-is-submitted-to-a-wrong-address', + content: ( +
+

+ If a role change was submitted to the wrong address, the change can be + revoked. For Rewards Address changes, navigate to "Roles" + → "Rewards Address" → "Cancel". For + Manager Address changes, go to "Roles" → "Manager + address" → "Cancel" +

+
+ ), +}; diff --git a/faq/items/roles-5.tsx b/faq/items/roles-5.tsx new file mode 100644 index 000000000..0be824e9e --- /dev/null +++ b/faq/items/roles-5.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { Faq } from 'types'; + +export const Roles5: Faq = { + title: 'What happens to rewards after changing the Rewards Address?', + anchor: 'what-happens-to-rewards-after-changing-the-rewards-address', + content: ( +
+

+ Rewards claimed to the previous Rewards Address remain there. After + changing the Rewards Address, all rewards and excess bond accumulated on + the bond balance can be claimed to the new Rewards Address. In the event + of validator withdrawal, upon claiming of the bond, it would also be + returned to the new Rewards Address. +

+
+ ), +}; diff --git a/faq/keys-1.md b/faq/keys-1.md deleted file mode 100644 index 615570dc5..000000000 --- a/faq/keys-1.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: How to set up a validator for CSM mainnet? ---- - -A detailed guide on preparing all the validation tools for CSM can be found [here](https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm). - -A shorter flow of setting up a CSM validator for mainnet looks as follows: - -1. [Generate new validator keys](https://dvt-homestaker.stakesaurus.com/keystore-generation-and-mev-boost/validator-key-generation) setting the `withdrawal_address` to the Lido Withdrawal Vault on **mainnet:** [`0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f`](https://etherscan.io/address/0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f) and specify the deposit amount of 32 ETH (do **NOT** make a deposit) -2. [Configure your validator client](https://dvt-homestaker.stakesaurus.com/native-solo-staking-setup/validator-client-setup) (and/or beacon node) setting the `fee_recipient` flag to the designated fee recipient address (Lido Execution Layer Rewards Vault) on **mainnet:** [`0x388C818CA8B9251b393131C08a736A67ccB19297`](https://etherscan.io/address/0x388C818CA8B9251b393131C08a736A67ccB19297) and import the newly generated CSM keystores -3. [Configure your MEV-Boost service](https://dvt-homestaker.stakesaurus.com/keystore-generation-and-mev-boost/set-up-and-configure-mev-boost). `Min-bid` may be configured either at MEV-Boost level or at the CL client, the current acceptable maximum value for min-bid is `0.07` [based on community consensus](https://research.lido.fi/t/lido-node-operator-mev-boost-min-bid-guidance/3347) and may change. `Builder-boost-factor` should be set to 100%, i.e. local and builder payloads should be treated with equal weights. The `relay` flags should be set to a list of values only using relays from [the list of Vetted MEV-Boost Relays for Lido CSM](https://enchanted-direction-844.notion.site/6d369eb33f664487800b0dedfe32171e?v=8e5d1f1276b0493caea8a2aa1517ed65). -4. [Upload the newly generated deposit data](https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm/upload-remove-view-validator-keys) file pertaining to your CSM keystores onto [the Lido CSM Widget](https://csm.lido.fi/) and provide the required bond amount in ETH/stETH/wstETH. Before uploading, make sure that nodes are synced, running, and ready for the validator activation. -5. Wait for your CSM validator keys to be deposited through the protocol and make sure your node remains online in the meantime! diff --git a/faq/keys-10.md b/faq/keys-10.md deleted file mode 100644 index 978d3d64e..000000000 --- a/faq/keys-10.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: When does a validator become withdrawn? -anchor: when-validator-become-withdrawn ---- - -On the Ethereum network, a validator can be withdrawn after successfully exiting from the consensus layer, but the exact timing of withdrawal depends on several factors related to Ethereum protocol mechanics: - -1. **Exit Queue**: When a validator initiates an exit, it enters an exit queue. The time required to exit depends on the number of validators exiting and the churn limit (the number of validators allowed to exit or enter per epoch). -2. **Withdrawal Process**: After exiting the active validator set, the validator enters a withdrawable state. This state is determined by the withdrawable epoch, which is set to the exit epoch + a minimum delay of 256 epochs (~27 hours). -3. **Finalization of Withdrawal**: Once the withdrawable epoch is reached, the validator balance will be transferred to the validator's withdrawal credentials (in the case of the Lido protocol, the Lido Withdrawal Vault) within the next iteration of the Consensus Layer withdrawal sweep cycle. How long this takes depends on the validator's position in the overall sweep cycle, and time difference between the withdrawable epoch and when its turn will come to be swept. Once the withdrawal has occurred, the fact of the withdrawal can be reported to CSM permissionlessly. Once that occurs, the part of the Node Operator’s bond used for this validator is released. At this point, the Node Operator can claim the bond on the Bond & Rewards Claim tab. diff --git a/faq/keys-11.md b/faq/keys-11.md deleted file mode 100644 index 88e7c56c3..000000000 --- a/faq/keys-11.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: What is a referrer? -onlyWithReferrer: true ---- - -A referrer is a software provider specializing in node/validator setup that integrated CSM into their tools. When a referrer directs solo stakers to join CSM via its tool, these Node Operators are marked as being referred from this provider. It doesn’t affect the Node Operators rewards in any way and is used just for the funnel-tracking purposes. diff --git a/faq/keys-12.md b/faq/keys-12.md deleted file mode 100644 index 7c2fc9e15..000000000 --- a/faq/keys-12.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: What to do in case of technical issues? ---- - -For community assistance, join the "CSM-mainnet" channel on the [Lido Discord server](https://discord.com/invite/lido) to seek advice and guidance. diff --git a/faq/keys-13.md b/faq/keys-13.md deleted file mode 100644 index df2a4bb3b..000000000 --- a/faq/keys-13.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: What is the CSM Stake Share Limit? -anchor: stake-share-limit ---- - -The stake share limit is a parameter defined for each Staking Module based on its risk profile. It determines the percentage of the total stake in the Lido Protocol that can be allocated to the module. Currently, the stake share limit for CSM is set at 2%. Once CSM reaches its stake share limit, new keys can still be uploaded, but deposits to these keys may take a very long time (e.g. months), if they are deposited to at all. These factors affect the possibility of new deposits to your uploaded keys: - -- The number of keys already in the deposit queue, and the position of your keys in this queue -- The number of keys that will exit from CSM -- Changes in the total volume of stake in the Lido Protocol (both net flows as well as whether overall Lido protocol stake increases or not) - -In other words, if keys had not been deposited to before CSM reached its limit, they may still be deposited to later if: - -- The overall stake volume in the Lido Protocol increases -- Keys exit from CSM, freeing up space for new keys -- The DAO decides to increase CSM's stake share limit - -While keys are awaiting deposit, Node Operators continue to receive daily bond rewards based on the bond they submitted. However, they do not receive Node Operator rewards, as the keys remain inactive until they are fully deposited. diff --git a/faq/keys-2.md b/faq/keys-2.md deleted file mode 100644 index fa478fdef..000000000 --- a/faq/keys-2.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Why upload a bond? ---- - -Submitting a bond serves as a risk mitigation measure for both the Ethereum network and the Lido protocol. - -There are several major reasons for a CSM Node Operator's bond to be penalized, including: - -- **The validator has been slashed.** In this case, the initial (minimal) slashing penalty is confiscated. `Penalty amount` = `1 ETH (EFFECTIVE_BALANCE / 32)`; -- **The operator has stolen EL rewards (MEV)**. `Penalty amount` = `amount stolen` + `fixed stealing fine`; -- **The validator's withdrawal balance is less than 32 ETH**. `Penalty amount` = `32` - `validator's withdrawal balance.` diff --git a/faq/keys-3.md b/faq/keys-3.md deleted file mode 100644 index e70c6dd97..000000000 --- a/faq/keys-3.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: How much bond is needed? -earlyAdoption: false -anchor: how-bond-is-calculated ---- - -The initial bond requirement for the first validator for the mainnet is 2.4 stETH. However, for [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), this amount is reduced to 1.5 stETH to incentivize early participation. - -The amount for the second and subsequent validators is 1.3 stETH - -For the mainnet, the values for the bond curve are the following: - -![curve.png](/assets/mainnet-curve-common.png) diff --git a/faq/keys-3a.md b/faq/keys-3a.md deleted file mode 100644 index 7ba99f09f..000000000 --- a/faq/keys-3a.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: How much bond is needed? -earlyAdoption: true -anchor: how-bond-is-calculated ---- - -The initial bond requirement for the first validator for the mainnet is 2.4 stETH. However, for [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), this amount is reduced to 1.5 stETH to incentivize early participation. - -The amount for the second and subsequent validators is 1.3 stETH - -For the mainnet, the values for the bond curve are the following: - -![curve.png](/assets/mainnet-curve-ea.png) diff --git a/faq/keys-4.md b/faq/keys-4.md deleted file mode 100644 index 4c793a8c4..000000000 --- a/faq/keys-4.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: What is the bond curve? -earlyAdoption: false ---- - -[The bond curve](https://operatorportal.lido.fi/modules/community-staking-module#block-2d1c307d95fc4f8ab7c32b7584f795cf) is a function that determines the amount of bond required for each subsequent validator operated by the node operator. For [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), a unique bond curve function is applied to incentivize early participation. - -For the mainnet, the values for the bond curve are the following: - -![curve.png](/assets/mainnet-curve-common.png) diff --git a/faq/keys-4a.md b/faq/keys-4a.md deleted file mode 100644 index 21e0eaf6c..000000000 --- a/faq/keys-4a.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: What is the bond curve? -earlyAdoption: true ---- - -[The bond curve](https://operatorportal.lido.fi/modules/community-staking-module#block-2d1c307d95fc4f8ab7c32b7584f795cf) is a function that determines the amount of bond required for each subsequent validator operated by the node operator. For [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), a unique bond curve function is applied to incentivize early participation. - -For the mainnet, the values for the bond curve are the following: - -![curve.png](/assets/mainnet-curve-ea.png) diff --git a/faq/keys-5.md b/faq/keys-5.md deleted file mode 100644 index 8539e45ab..000000000 --- a/faq/keys-5.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Difference between bond types (ETH, stETH, wstETH)? ---- - -Bonds are stored in the form of stETH to so that participation as a Node Operator is more capital efficient than if the bond were un-staked (or could only be staked if sufficient deposits to fill the submitted validators were present). While node operators can submit bond in ETH, stETH, or wstETH, any token other than stETH is converted to stETH for consistency in bond format. diff --git a/faq/keys-6.md b/faq/keys-6.md deleted file mode 100644 index c7651403a..000000000 --- a/faq/keys-6.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: When does a validator become active? -anchor: when-validator-become-active ---- - -After key submission, and if keys have been successfully validated, two actions are required for a validator to be activated: - -1. **Deposit by Lido Protocol**: The time to deposit a validator is unpredictable and depends on factors such as total stake inflows and outflows, gas considerations, module shares, CSM deposit queue size, and the Node Operator's place in the queue. - - You can subscribe to [the important CSM events](https://docs.lido.fi/staking-modules/csm/guides/events) to stay notified about your validator being deposited to. - - Read more information about the deposits flow [here](https://operatorportal.lido.fi/modules/community-staking-module#block-90b8ff95edc64cf7a051584820219616). - -2. **Activation on Ethereum Network**: Once deposited, the validator enters the Beacon Chain activation queue. The time to activation depends on the total number of validators in the queue awaiting activation and the rate of queue processing, which varies based on the total number of active Ethereum validators. - - You can check if the keys are activated on the [Keys tab](https://csm.lido.fi/keys) or on [beaconcha.in](http://beaconcha.in/) diff --git a/faq/keys-7.md b/faq/keys-7.md deleted file mode 100644 index 2049a4e0d..000000000 --- a/faq/keys-7.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Why pay for key deletion? ---- - -Key deletion incurs a removal fee of 0.05 ETH, which is deducted from the Node Operator's bond per each deleted key to cover the maximal possible operational costs associated with the queue processing. This fee is intended to protect the module from potential DoS attacks by malicious actors who could clog the queue with empty slots by adding and removing keys, and covers the maximal possible operational costs associated with the queue processing. The fee discourages misuse, keeping the system clear of invalid keys or keys that don’t end up being deposited to. diff --git a/faq/keys-8.md b/faq/keys-8.md deleted file mode 100644 index 79c65c687..000000000 --- a/faq/keys-8.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Can't see the key for deletion? ---- - -Only keys that have not been deposited yet can be deleted. If a key has already been deposited, the only way to retrieve the bond is [to exit the validator on the Consensus Layer (CL)](https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm/exiting-csm-validators). Once withdrawn, the node operator can claim the excess bond. diff --git a/faq/keys-9.md b/faq/keys-9.md deleted file mode 100644 index c1361d387..000000000 --- a/faq/keys-9.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: How to stop validating in CSM? ---- - -Exiting CSM validator keys works the same way as exiting solo staking validator keys. The guide on how to exit the validator can be found [here](https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm/exiting-csm-validators#manual-exit). diff --git a/faq/locked-1.md b/faq/locked-1.md deleted file mode 100644 index ea31fa37f..000000000 --- a/faq/locked-1.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Why is the bond locked? ---- - -Bond may be locked in the case of delayed penalties, typically for MEV stealing event reported by a dedicated committee. This measure ensures that node operators are held accountable for any misbehavior or rule violations. diff --git a/faq/locked-2.md b/faq/locked-2.md deleted file mode 100644 index 4aeaf5450..000000000 --- a/faq/locked-2.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: How to unlock the bond? ---- - -To unlock the bond, the penalty amount, which includes the stolen amount and a fixed stealing fine, must be compensated on the "Locked bond" tab. This action can be performed from the Manager Address of the Node Operator. - -If there are disputes regarding the penalty, node operators can start a public discussion about the penalty applied on the Lido research forum under the [CSM Support](https://research.lido.fi/c/csm-support/21) category. diff --git a/faq/locked-3.md b/faq/locked-3.md deleted file mode 100644 index d811e26fa..000000000 --- a/faq/locked-3.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Consequences of not compensating? ---- - -In case of refusal to compensate the penalty, a protocol rule violation occurs which results in the reset of all node operator benefits. The locked bond is burned to compensate all stETH holders for the rewards stolen. diff --git a/faq/main-1.md b/faq/main-1.md deleted file mode 100644 index d543ade1c..000000000 --- a/faq/main-1.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Why run an Ethereum validator? ---- - -Running an Ethereum validator allows one to: - -1. **Receive Staking Rewards**: Validators get network rewards for performing their duties on the Ethereum blockchain (note: incorrectly or not performing duties incurs penalties). -2. **Support the Network**: By running a validator, you actively contribute to the decentralization and security of the Ethereum network. Validators play a crucial role in reaching consensus and validating transactions, which enhances the network's reliability and resilience. -3. **Learn and Engage with the community**: Operating a validator node provides valuable insights into blockchain technology and consensus mechanisms. Through hands-on experience, individuals can deepen their understanding of Ethereum's inner workings. Moreover, it provides an opportunity to engage with the Ethereum community, share knowledge, and contribute to the network's development. diff --git a/faq/main-2.md b/faq/main-2.md deleted file mode 100644 index 21c6b4a8a..000000000 --- a/faq/main-2.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: What is required to be a Node Operator in CSM? ---- - -Node operation in CSM involves a long-term commitment to Ethereum's decentralization. Responsibilities include: - -- **Hardware Setup**: Setting up a computer that meets the system requirements for running validator nodes. -- **Configuration**: Properly configuring nodes and validators, ensuring they are in sync with the Ethereum blockchain and other network participants. -- **Security Measures**: Implementing robust security measures to safeguard against external threats and internal vulnerabilities. -- **Maintenance**: Sustaining ongoing maintenance throughout the validators' lifespan, which involves monitoring performance, troubleshooting issues, and applying necessary updates. diff --git a/faq/main-3.md b/faq/main-3.md deleted file mode 100644 index 32d58fae2..000000000 --- a/faq/main-3.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: What do node operators receive in CSM? ---- - -Node operators benefit from: - -- **Daily Bond Rebase**: The collateral for CSM NOs is eligible for [rewards through stETH's rebase](https://help.lido.fi/en/articles/5230610-what-is-steth), even before validator activation. -- **Socialized Rewards**: Rewards are smoothed across the largest validator set, mitigating volatility. This means that even in the event of small outages or disruptions, node operators can still receive rewards, reducing the risk of rewards loss. diff --git a/faq/main-4.md b/faq/main-4.md deleted file mode 100644 index 72d4d1482..000000000 --- a/faq/main-4.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: What are the risks of running a validator? ---- - -Node operators face several risks, including: - -1. **Technical Risk**: Maintaining reliable and secure hardware and software setups is essential. Any technical failure or vulnerability in the validator setup could lead to penalties. -2. **Penalties for Misbehavior**: Validators can be penalized for various reasons, such as going offline or attempting to manipulate the network. -3. **Market Risk**: The value of ETH can fluctuate significantly, impacting the value of the validators' staked ETH. -4. **Network Risk**: Validators are part of a decentralized network, and the security and stability of the Ethereum network as a whole can affect individual validators. Events such as network attacks or protocol upgrades may impact validator operations, leading to potential disruptions or losses. -5. **Operational Risk**: Validators require ongoing maintenance and monitoring to ensure smooth operation. Any operational issues, such as hardware failures or connectivity issues, could disrupt validator performance and result in rewards losses. -6. **Slashing Risk**: Validators can be slashed, meaning they lose a portion of their staked ETH, for violating network rules or behaving maliciously. Slashing can occur due to actions such as double signing or failing to validate correctly, resulting in significant penalties. diff --git a/faq/main-5.md b/faq/main-5.md deleted file mode 100644 index 68b4053b6..000000000 --- a/faq/main-5.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: How does CSM work? ---- - -Refer to [the CSM blog post](https://blog.lido.fi/lido-community-staking-an-overview/) for an overview, or [the CSM page](https://operatorportal.lido.fi/modules/community-staking-module) for a more detailed explanation of its mechanics and functionalities. diff --git a/faq/main-6.md b/faq/main-6.md deleted file mode 100644 index e233beedc..000000000 --- a/faq/main-6.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: What makes CSM unique? ---- - -CSM provides several unique features to attract and benefit community stakers: - -- **Rewards Smoothing**: Rewards, including Execution Layer (EL) rewards and MEV, are smoothed with other modules to provide more stable rewards comparable to operating validators solo. -- **Low Bond Requirement**: A low bond for node operators makes participation more accessible to a broader range of prospective operators. -- **Exclusive Use of ETH (stETH)**: CSM exclusively uses ETH ((w)stETH) for bond and rewards, eliminating the need for other assets and simplifying the process for node operators. The bond can be submitted as ETH, wstETH, or stETH, and both bond and rewards can be withdrawn in any of the three forms (withdrawals in the form of ETH follow the [normal Lido on Ethereum unstaking process](https://help.lido.fi/en/articles/7858323-how-do-i-unstake-my-steth)). -- **Enhanced User Experience**: Accessible through a multitude of options -- from a web UI to integrations with Dappnode, Stereum, Eth-Docker, Sedge, Stereum, CoinPillar, etc., CSM offers a leading user-friendly experience, with reduced gas fees for on-chain operations and simplified transactions for joining and claiming rewards. -- **Higher Reward Potential**: Node operators are potentially able to earn more rewards compared to vanilla solo staking, making CSM an attractive option for operators looking to run more validators to earn rewards. diff --git a/faq/main-7.md b/faq/main-7.md deleted file mode 100644 index d8d42774e..000000000 --- a/faq/main-7.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: How much bond is needed? -earlyAdoption: false ---- - -The initial bond requirement for the first validator for the mainnet is 2.4 stETH. However, for [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), this amount is reduced to 1.5 stETH to incentivize early participation. - -The amount for the second and subsequent validators is 1.3 stETH - -For the mainnet, the values for the bond curve are the following: - -![curve.png](/assets/mainnet-curve-common.png) diff --git a/faq/main-7a.md b/faq/main-7a.md deleted file mode 100644 index 77dd1c74c..000000000 --- a/faq/main-7a.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: How much bond is needed? -earlyAdoption: true ---- - -The initial bond requirement for the first validator for the mainnet is 2.4 stETH. However, for [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), this amount is reduced to 1.5 stETH to incentivize early participation. - -The amount for the second and subsequent validators is 1.3 stETH - -For the mainnet, the values for the bond curve are the following: - -![curve.png](/assets/mainnet-curve-ea.png) diff --git a/faq/main-8.md b/faq/main-8.md deleted file mode 100644 index 5e3e9e79a..000000000 --- a/faq/main-8.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: How can I get help? ---- - -For community assistance, join the "CSM-mainnet" channel on the [Lido Discord server](https://discord.com/invite/lido) to seek advice and guidance. diff --git a/faq/roles-1.md b/faq/roles-1.md deleted file mode 100644 index 430183f79..000000000 --- a/faq/roles-1.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: What are rewards and Manager Addresses? ---- - -There are two addresses associated with your Node Operator that have different scope of responsibilities for managing your Node Operator. - -The Rewards Address is used for: - -- Claiming bond and rewards -- Adding extra bond amount -- Proposing a new Rewards Address -- Resetting the Manager Address to the current Rewards Address - -The Manager Address is used for: - -- Adding new keys -- Removing existing keys -- Adding extra bond amount -- Claiming bond and rewards to the Rewards Address -- Covering locked bond -- Proposing a new Manager Address - -Read more about addresses management [here](https://operatorportal.lido.fi/modules/community-staking-module#block-d3ad2b2bd3994a06b19dccc0794ac8d6). diff --git a/faq/roles-2.md b/faq/roles-2.md deleted file mode 100644 index 348752d1d..000000000 --- a/faq/roles-2.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Why should these addresses be different? ---- - -It's recommended to use different addresses for security reasons. For example, a hot wallet may be used for the Manager Address to simplify daily operations, while a cold wallet (or something like a Safe) is preferable for the Rewards Address to enhance security. - -Read more about addresses management [here](https://operatorportal.lido.fi/modules/community-staking-module#block-d3ad2b2bd3994a06b19dccc0794ac8d6). diff --git a/faq/roles-3.md b/faq/roles-3.md deleted file mode 100644 index 893ec2914..000000000 --- a/faq/roles-3.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: How to accept a change in address request? ---- - -To accept a change in address request, connect to the CSM widget with the new address, navigate to the "Roles" → "Inbox requests" tab, select and accept the request, and confirm the transaction in your wallet. Changes are made once the transaction is processed. diff --git a/faq/roles-4.md b/faq/roles-4.md deleted file mode 100644 index 1734995e6..000000000 --- a/faq/roles-4.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: What to do if the change is submitted to a wrong address? ---- - -If a role change was submitted to the wrong address, the change can be revoked. For Rewards Address changes, navigate to "Roles" → "Rewards Address" → "Revoke". For Manager Address changes, go to "Roles" → "Manager Address" → "Revoke" diff --git a/faq/roles-5.md b/faq/roles-5.md deleted file mode 100644 index 90b335a54..000000000 --- a/faq/roles-5.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: What happens to rewards after changing the Rewards Address? ---- - -Rewards claimed to the previous Rewards Address remain there. After changing the Rewards Address, all rewards and excess bond accumulated on the bond balance can be claimed to the new Rewards Address. In the event of validator withdrawal, upon claiming of the bond, it would also be returned to the new Rewards Address. diff --git a/faq/testnet-bond-1.md b/faq/testnet-bond-1.md deleted file mode 100644 index f4cc4ef44..000000000 --- a/faq/testnet-bond-1.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: What rewards do I get in CSM? ---- - -When CSM operators use the Lido protocol to run validators, they can receive two types of rewards: - -- **Node Operator rewards**: a share of rewards from staker locked stake amount, currently calculated pro-rata based on validators operated as a share of total protocol validators, with [possible reductions for bad performance](https://operatorportal.lido.fi/modules/community-staking-module#block-c6dc8d00f13243fcb17de3fa07ecc52c). -- **Bond rebase**: staking rewards pertaining to the bonded tokens (stETH). diff --git a/faq/testnet-bond-2.md b/faq/testnet-bond-2.md deleted file mode 100644 index 1697d259a..000000000 --- a/faq/testnet-bond-2.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: How often do I get rewards? ---- - -**Node Operator rewards** on testnet are calculated and made claimable by the CSM Oracle **every 7 days**. Rewards do not have to be claimed during every reporting frame, and can be left to accumulate to be claimed later. - -**Bond rebase part** of the rewards come from stETH being a rebasing token and the bond being stored in stETH. After each Accounting Oracle report that happens on testnet **every 12 epochs (1hr 20min)**, the share rate changes. Hence, the same amount of stETH shares will now be equal to a bigger stETH token balance. diff --git a/faq/testnet-bond-3.md b/faq/testnet-bond-3.md deleted file mode 100644 index de49ca7ec..000000000 --- a/faq/testnet-bond-3.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Why didn’t I get rewards? -anchor: why-did-not-i-get-rewards ---- - -There are two main reasons of you getting no reward within a frame: - -1. If your validator’s performance was below the threshold within the CSM Performance Oracle frame (7 days for testnet) the validator does not receive rewards for the given frame. Read more about [the CSM Performance Oracle](https://operatorportal.lido.fi/modules/community-staking-module#block-c6dc8d00f13243fcb17de3fa07ecc52c). -2. [Your Node Operator has stuck keys](https://operatorportal.lido.fi/modules/community-staking-module#block-0ed61a4c0a5a439bbb4be20e814b4e38) due to not exiting a validator requested for exit timely. diff --git a/faq/testnet-bond-4.md b/faq/testnet-bond-4.md deleted file mode 100644 index 4991f37c6..000000000 --- a/faq/testnet-bond-4.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Why add a bond? ---- - -Adding bond is a prevention measure to avoid Exit Request for your validators if they became unbonded. [Unbonded validators](https://docs.lido.fi/staking-modules/csm/guides/unbonded-validators) appear if the Node Operator's bond is no longer sufficient to cover all the validator keys uploaded to CSM by the Node Operator. - -If a [penalty](https://operatorportal.lido.fi/modules/community-staking-module#block-3951aa72ba1e471bafe95b40fef65d2b) was already applied, there is a relatively short period of time until the next VEBO report, which most likely will contain a validator Exit Request. During this period in between penalty application and the next VEBO report, Node Operators must top up bond to avoid Exit Requests for their validator(s). - -**Warning:** If the unbonded validator has already been requested to exit, Node Operators can only exit it. The bond top-up after the Exit Request will not reverse the Exit Request. diff --git a/faq/testnet-bond-5.md b/faq/testnet-bond-5.md deleted file mode 100644 index 90af76967..000000000 --- a/faq/testnet-bond-5.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: How to claim ETH using a withdrawal NFT -anchor: how-to-claim-eth ---- - -Claiming bond and rewards in a form of ETH constitutes an stETH withdrawal process (unstake). - -The withdrawal process consists of several steps you need to do: - -- **Submit a withdrawal request** by choosing ETH as a token for bond/rewards claim. As a result of this step, you will receive a withdrawal NFT. -- **Claim your ETH** after request fulfilment. The fulfilment process takes 1-5 days (or longer), [depending on a variety of factors](https://help.lido.fi/en/articles/7858315-how-long-does-an-ethereum-withdrawal-take). To know if your ETH is ready to be claimed you, can check its status on the [Claim page](https://stake-holesky.testnet.fi/withdrawals/claim). If your request is marked as “**Ready to claim**”, it is time for you to get your ETH back. - -For more information about withdrawals, [follow the page](https://help.lido.fi/en/collections/3993867-ethereum-withdrawals). diff --git a/faq/testnet-keys-1.md b/faq/testnet-keys-1.md deleted file mode 100644 index 1e5732bf3..000000000 --- a/faq/testnet-keys-1.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: How to set up a validator for CSM testnet? ---- - -A detailed guide on preparing all the validation tools for CSM can be found [here](https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm). - -A shorter flow of setting up a CSM validator for **testnet** looks as follows: - -1. [Generate new validator keys](https://dvt-homestaker.stakesaurus.com/keystore-generation-and-mev-boost/validator-key-generation) setting the `withdrawal_address` to the [Lido Withdrawal Vault](https://holesky.etherscan.io/address/0xF0179dEC45a37423EAD4FaD5fCb136197872EAd9) on **Holesky:** [`0xF0179dEC45a37423EAD4FaD5fCb136197872EAd9`](https://holesky.etherscan.io/address/0xF0179dEC45a37423EAD4FaD5fCb136197872EAd9) and specify the deposit amount of 32 ETH (do **NOT** make a deposit) -2. [Configure your validator client](https://dvt-homestaker.stakesaurus.com/native-solo-staking-setup/validator-client-setup) (and/or beacon node) setting the `fee_recipient` flag to the designated fee recipient address (Lido Execution Layer Rewards Vault) on **Holesky:** [`0xE73a3602b99f1f913e72F8bdcBC235e206794Ac8`](https://holesky.etherscan.io/address/0xE73a3602b99f1f913e72F8bdcBC235e206794Ac8) and import the newly generated CSM keystores -3. [Configure your MEV-Boost service](https://dvt-homestaker.stakesaurus.com/keystore-generation-and-mev-boost/set-up-and-configure-mev-boost). Do not set the `min-bid` flag (or set 0) and set the `relay` flags only to [the list of designated MEV relays for Lido CSM on **Holesky**](https://enchanted-direction-844.notion.site/6d369eb33f664487800b0dedfe32171e?v=985cb7e521de43d78c67b7ad29adec84) -4. [Upload the newly generated deposit data](https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm/upload-remove-view-validator-keys) file pertaining to your CSM keystores onto [the Lido CSM Widget](https://csm.testnet.fi/) and provide the required bond amount in Holesky ETH/stETH/wstETH. Before uploading, make sure that nodes are synced, running, and ready for the validator activation. -5. Wait for your CSM validator keys to be deposited through the protocol and make sure your node remains online in the meantime! diff --git a/faq/testnet-keys-10.md b/faq/testnet-keys-10.md deleted file mode 100644 index 978d3d64e..000000000 --- a/faq/testnet-keys-10.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: When does a validator become withdrawn? -anchor: when-validator-become-withdrawn ---- - -On the Ethereum network, a validator can be withdrawn after successfully exiting from the consensus layer, but the exact timing of withdrawal depends on several factors related to Ethereum protocol mechanics: - -1. **Exit Queue**: When a validator initiates an exit, it enters an exit queue. The time required to exit depends on the number of validators exiting and the churn limit (the number of validators allowed to exit or enter per epoch). -2. **Withdrawal Process**: After exiting the active validator set, the validator enters a withdrawable state. This state is determined by the withdrawable epoch, which is set to the exit epoch + a minimum delay of 256 epochs (~27 hours). -3. **Finalization of Withdrawal**: Once the withdrawable epoch is reached, the validator balance will be transferred to the validator's withdrawal credentials (in the case of the Lido protocol, the Lido Withdrawal Vault) within the next iteration of the Consensus Layer withdrawal sweep cycle. How long this takes depends on the validator's position in the overall sweep cycle, and time difference between the withdrawable epoch and when its turn will come to be swept. Once the withdrawal has occurred, the fact of the withdrawal can be reported to CSM permissionlessly. Once that occurs, the part of the Node Operator’s bond used for this validator is released. At this point, the Node Operator can claim the bond on the Bond & Rewards Claim tab. diff --git a/faq/testnet-keys-11.md b/faq/testnet-keys-11.md deleted file mode 100644 index 88e7c56c3..000000000 --- a/faq/testnet-keys-11.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: What is a referrer? -onlyWithReferrer: true ---- - -A referrer is a software provider specializing in node/validator setup that integrated CSM into their tools. When a referrer directs solo stakers to join CSM via its tool, these Node Operators are marked as being referred from this provider. It doesn’t affect the Node Operators rewards in any way and is used just for the funnel-tracking purposes. diff --git a/faq/testnet-keys-12.md b/faq/testnet-keys-12.md deleted file mode 100644 index 1b15238d0..000000000 --- a/faq/testnet-keys-12.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: What to do in case of technical issues? ---- - -For community assistance, join the "[CSM-testnet](https://discord.com/channels/761182643269795850/1255114351120089148)" channel on the [Lido Discord server](https://discord.com/invite/lido) to seek advice and guidance. diff --git a/faq/testnet-keys-13.md b/faq/testnet-keys-13.md deleted file mode 100644 index 2dd0f9720..000000000 --- a/faq/testnet-keys-13.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: What is the CSM Stake Share Limit? -anchor: stake-share-limit ---- - -The stake share limit is a parameter defined for each Staking Module based on its risk profile. It determines the percentage of the total stake in the Lido Protocol that can be allocated to the module. Currently, the stake share limit for CSM is set at 15%. Once CSM reaches its stake share limit, new keys can still be uploaded, but deposits to these keys may take a very long time (e.g. months), if they are deposited to at all. These factors affect the possibility of new deposits to your uploaded keys: - -- The number of keys already in the deposit queue, and the position of your keys in this queue -- The number of keys that will exit from CSM -- Changes in the total volume of stake in the Lido Protocol (both net flows as well as whether overall Lido protocol stake increases or not) - -In other words, if keys had not been deposited to before CSM reached its limit, they may still be deposited to later if: - -- The overall stake volume in the Lido Protocol increases -- Keys exit from CSM, freeing up space for new keys -- The DAO decides to increase CSM's stake share limit - -While keys are awaiting deposit, Node Operators continue to receive daily bond rewards based on the bond they submitted. However, they do not receive Node Operator rewards, as the keys remain inactive until they are fully deposited. diff --git a/faq/testnet-keys-2.md b/faq/testnet-keys-2.md deleted file mode 100644 index fa478fdef..000000000 --- a/faq/testnet-keys-2.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Why upload a bond? ---- - -Submitting a bond serves as a risk mitigation measure for both the Ethereum network and the Lido protocol. - -There are several major reasons for a CSM Node Operator's bond to be penalized, including: - -- **The validator has been slashed.** In this case, the initial (minimal) slashing penalty is confiscated. `Penalty amount` = `1 ETH (EFFECTIVE_BALANCE / 32)`; -- **The operator has stolen EL rewards (MEV)**. `Penalty amount` = `amount stolen` + `fixed stealing fine`; -- **The validator's withdrawal balance is less than 32 ETH**. `Penalty amount` = `32` - `validator's withdrawal balance.` diff --git a/faq/testnet-keys-3.md b/faq/testnet-keys-3.md deleted file mode 100644 index a4c6e0db4..000000000 --- a/faq/testnet-keys-3.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: How much bond is needed? -earlyAdoption: false -anchor: how-bond-is-calculated ---- - -The initial bond requirement for the first validator for the testnet is 2 stETH. However, for [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), this amount is reduced to 1.5 stETH to incentivize early participation. - -Subsequent bond amounts depend on the total number of validators operated by the node operator and follow a specific function known as the “[bond curve](https://operatorportal.lido.fi/modules/community-staking-module#block-2d1c307d95fc4f8ab7c32b7584f795cf)”, which adjusts the bond requirement based on the operator's validator count. - -For the testnet, the values for the bond curve are the following: - -![curve.png](/assets/curve-common.png) diff --git a/faq/testnet-keys-3a.md b/faq/testnet-keys-3a.md deleted file mode 100644 index f1ad7a063..000000000 --- a/faq/testnet-keys-3a.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: How much bond is needed? -earlyAdoption: true -anchor: how-bond-is-calculated ---- - -The initial bond requirement for the first validator for the testnet is 2 stETH. However, for [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), this amount is reduced to 1.5 stETH to incentivize early participation. - -Subsequent bond amounts depend on the total number of validators operated by the node operator and follow a specific function known as the “[bond curve](https://operatorportal.lido.fi/modules/community-staking-module#block-2d1c307d95fc4f8ab7c32b7584f795cf)”, which adjusts the bond requirement based on the operator's validator count. - -For the testnet, the values for the bond curve are the following: - -![curve.png](/assets/curve-ea.png) diff --git a/faq/testnet-keys-4.md b/faq/testnet-keys-4.md deleted file mode 100644 index 731c6deda..000000000 --- a/faq/testnet-keys-4.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: What is the bond curve? -earlyAdoption: false ---- - -[The bond curve](https://operatorportal.lido.fi/modules/community-staking-module#block-2d1c307d95fc4f8ab7c32b7584f795cf) is a function that determines the amount of bond required for each subsequent validator operated by the node operator. For [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), a unique bond curve function is applied to incentivize early participation. - -For the testnet, the values for the bond curve are the following: - -![curve.png](/assets/curve-common.png) diff --git a/faq/testnet-keys-4a.md b/faq/testnet-keys-4a.md deleted file mode 100644 index 5b43be9be..000000000 --- a/faq/testnet-keys-4a.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: What is the bond curve? -earlyAdoption: true ---- - -[The bond curve](https://operatorportal.lido.fi/modules/community-staking-module#block-2d1c307d95fc4f8ab7c32b7584f795cf) is a function that determines the amount of bond required for each subsequent validator operated by the node operator. For [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), a unique bond curve function is applied to incentivize early participation. - -For the testnet, the values for the bond curve are the following: - -![curve.png](/assets/curve-ea.png) diff --git a/faq/testnet-keys-5.md b/faq/testnet-keys-5.md deleted file mode 100644 index 8539e45ab..000000000 --- a/faq/testnet-keys-5.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Difference between bond types (ETH, stETH, wstETH)? ---- - -Bonds are stored in the form of stETH to so that participation as a Node Operator is more capital efficient than if the bond were un-staked (or could only be staked if sufficient deposits to fill the submitted validators were present). While node operators can submit bond in ETH, stETH, or wstETH, any token other than stETH is converted to stETH for consistency in bond format. diff --git a/faq/testnet-keys-6.md b/faq/testnet-keys-6.md deleted file mode 100644 index 0c2bdddac..000000000 --- a/faq/testnet-keys-6.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: When does a validator become active? -anchor: when-validator-become-active ---- - -After key submission, and if keys have been successfully validated, two actions are required for a validator to be activated: - -1. **Deposit by Lido Protocol**: The time to deposit a validator is unpredictable and depends on factors such as total stake inflows and outflows, gas considerations, module shares, CSM deposit queue size, and the Node Operator's place in the queue. - - You can subscribe to [the important CSM events](https://docs.lido.fi/staking-modules/csm/guides/events) to stay notified about your validator being deposited to. - - Read more information about the deposits flow [here](https://operatorportal.lido.fi/modules/community-staking-module#block-90b8ff95edc64cf7a051584820219616). - -2. **Activation on Ethereum Network**: Once deposited, the validator enters the Beacon Chain activation queue. The time to activation depends on the total number of validators in the queue awaiting activation and the rate of queue processing, which varies based on the total number of active Ethereum validators. - - You can check if the keys are activated on the [Keys tab](https://csm.testnet.fi/keys) or on [beaconcha.in](http://beaconcha.in/) diff --git a/faq/testnet-keys-7.md b/faq/testnet-keys-7.md deleted file mode 100644 index 2049a4e0d..000000000 --- a/faq/testnet-keys-7.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Why pay for key deletion? ---- - -Key deletion incurs a removal fee of 0.05 ETH, which is deducted from the Node Operator's bond per each deleted key to cover the maximal possible operational costs associated with the queue processing. This fee is intended to protect the module from potential DoS attacks by malicious actors who could clog the queue with empty slots by adding and removing keys, and covers the maximal possible operational costs associated with the queue processing. The fee discourages misuse, keeping the system clear of invalid keys or keys that don’t end up being deposited to. diff --git a/faq/testnet-keys-8.md b/faq/testnet-keys-8.md deleted file mode 100644 index 79c65c687..000000000 --- a/faq/testnet-keys-8.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Can't see the key for deletion? ---- - -Only keys that have not been deposited yet can be deleted. If a key has already been deposited, the only way to retrieve the bond is [to exit the validator on the Consensus Layer (CL)](https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm/exiting-csm-validators). Once withdrawn, the node operator can claim the excess bond. diff --git a/faq/testnet-keys-9.md b/faq/testnet-keys-9.md deleted file mode 100644 index c1361d387..000000000 --- a/faq/testnet-keys-9.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: How to stop validating in CSM? ---- - -Exiting CSM validator keys works the same way as exiting solo staking validator keys. The guide on how to exit the validator can be found [here](https://dvt-homestaker.stakesaurus.com/bonded-validators-setup/lido-csm/exiting-csm-validators#manual-exit). diff --git a/faq/testnet-locked-1.md b/faq/testnet-locked-1.md deleted file mode 100644 index ea31fa37f..000000000 --- a/faq/testnet-locked-1.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Why is the bond locked? ---- - -Bond may be locked in the case of delayed penalties, typically for MEV stealing event reported by a dedicated committee. This measure ensures that node operators are held accountable for any misbehavior or rule violations. diff --git a/faq/testnet-locked-2.md b/faq/testnet-locked-2.md deleted file mode 100644 index 4aeaf5450..000000000 --- a/faq/testnet-locked-2.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: How to unlock the bond? ---- - -To unlock the bond, the penalty amount, which includes the stolen amount and a fixed stealing fine, must be compensated on the "Locked bond" tab. This action can be performed from the Manager Address of the Node Operator. - -If there are disputes regarding the penalty, node operators can start a public discussion about the penalty applied on the Lido research forum under the [CSM Support](https://research.lido.fi/c/csm-support/21) category. diff --git a/faq/testnet-locked-3.md b/faq/testnet-locked-3.md deleted file mode 100644 index d811e26fa..000000000 --- a/faq/testnet-locked-3.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Consequences of not compensating? ---- - -In case of refusal to compensate the penalty, a protocol rule violation occurs which results in the reset of all node operator benefits. The locked bond is burned to compensate all stETH holders for the rewards stolen. diff --git a/faq/testnet-main-1.md b/faq/testnet-main-1.md deleted file mode 100644 index d543ade1c..000000000 --- a/faq/testnet-main-1.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Why run an Ethereum validator? ---- - -Running an Ethereum validator allows one to: - -1. **Receive Staking Rewards**: Validators get network rewards for performing their duties on the Ethereum blockchain (note: incorrectly or not performing duties incurs penalties). -2. **Support the Network**: By running a validator, you actively contribute to the decentralization and security of the Ethereum network. Validators play a crucial role in reaching consensus and validating transactions, which enhances the network's reliability and resilience. -3. **Learn and Engage with the community**: Operating a validator node provides valuable insights into blockchain technology and consensus mechanisms. Through hands-on experience, individuals can deepen their understanding of Ethereum's inner workings. Moreover, it provides an opportunity to engage with the Ethereum community, share knowledge, and contribute to the network's development. diff --git a/faq/testnet-main-2.md b/faq/testnet-main-2.md deleted file mode 100644 index 21c6b4a8a..000000000 --- a/faq/testnet-main-2.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: What is required to be a Node Operator in CSM? ---- - -Node operation in CSM involves a long-term commitment to Ethereum's decentralization. Responsibilities include: - -- **Hardware Setup**: Setting up a computer that meets the system requirements for running validator nodes. -- **Configuration**: Properly configuring nodes and validators, ensuring they are in sync with the Ethereum blockchain and other network participants. -- **Security Measures**: Implementing robust security measures to safeguard against external threats and internal vulnerabilities. -- **Maintenance**: Sustaining ongoing maintenance throughout the validators' lifespan, which involves monitoring performance, troubleshooting issues, and applying necessary updates. diff --git a/faq/testnet-main-3.md b/faq/testnet-main-3.md deleted file mode 100644 index 32d58fae2..000000000 --- a/faq/testnet-main-3.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: What do node operators receive in CSM? ---- - -Node operators benefit from: - -- **Daily Bond Rebase**: The collateral for CSM NOs is eligible for [rewards through stETH's rebase](https://help.lido.fi/en/articles/5230610-what-is-steth), even before validator activation. -- **Socialized Rewards**: Rewards are smoothed across the largest validator set, mitigating volatility. This means that even in the event of small outages or disruptions, node operators can still receive rewards, reducing the risk of rewards loss. diff --git a/faq/testnet-main-4.md b/faq/testnet-main-4.md deleted file mode 100644 index 72d4d1482..000000000 --- a/faq/testnet-main-4.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: What are the risks of running a validator? ---- - -Node operators face several risks, including: - -1. **Technical Risk**: Maintaining reliable and secure hardware and software setups is essential. Any technical failure or vulnerability in the validator setup could lead to penalties. -2. **Penalties for Misbehavior**: Validators can be penalized for various reasons, such as going offline or attempting to manipulate the network. -3. **Market Risk**: The value of ETH can fluctuate significantly, impacting the value of the validators' staked ETH. -4. **Network Risk**: Validators are part of a decentralized network, and the security and stability of the Ethereum network as a whole can affect individual validators. Events such as network attacks or protocol upgrades may impact validator operations, leading to potential disruptions or losses. -5. **Operational Risk**: Validators require ongoing maintenance and monitoring to ensure smooth operation. Any operational issues, such as hardware failures or connectivity issues, could disrupt validator performance and result in rewards losses. -6. **Slashing Risk**: Validators can be slashed, meaning they lose a portion of their staked ETH, for violating network rules or behaving maliciously. Slashing can occur due to actions such as double signing or failing to validate correctly, resulting in significant penalties. diff --git a/faq/testnet-main-5.md b/faq/testnet-main-5.md deleted file mode 100644 index 68b4053b6..000000000 --- a/faq/testnet-main-5.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: How does CSM work? ---- - -Refer to [the CSM blog post](https://blog.lido.fi/lido-community-staking-an-overview/) for an overview, or [the CSM page](https://operatorportal.lido.fi/modules/community-staking-module) for a more detailed explanation of its mechanics and functionalities. diff --git a/faq/testnet-main-6.md b/faq/testnet-main-6.md deleted file mode 100644 index e233beedc..000000000 --- a/faq/testnet-main-6.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: What makes CSM unique? ---- - -CSM provides several unique features to attract and benefit community stakers: - -- **Rewards Smoothing**: Rewards, including Execution Layer (EL) rewards and MEV, are smoothed with other modules to provide more stable rewards comparable to operating validators solo. -- **Low Bond Requirement**: A low bond for node operators makes participation more accessible to a broader range of prospective operators. -- **Exclusive Use of ETH (stETH)**: CSM exclusively uses ETH ((w)stETH) for bond and rewards, eliminating the need for other assets and simplifying the process for node operators. The bond can be submitted as ETH, wstETH, or stETH, and both bond and rewards can be withdrawn in any of the three forms (withdrawals in the form of ETH follow the [normal Lido on Ethereum unstaking process](https://help.lido.fi/en/articles/7858323-how-do-i-unstake-my-steth)). -- **Enhanced User Experience**: Accessible through a multitude of options -- from a web UI to integrations with Dappnode, Stereum, Eth-Docker, Sedge, Stereum, CoinPillar, etc., CSM offers a leading user-friendly experience, with reduced gas fees for on-chain operations and simplified transactions for joining and claiming rewards. -- **Higher Reward Potential**: Node operators are potentially able to earn more rewards compared to vanilla solo staking, making CSM an attractive option for operators looking to run more validators to earn rewards. diff --git a/faq/testnet-main-7.md b/faq/testnet-main-7.md deleted file mode 100644 index f1e10d2c5..000000000 --- a/faq/testnet-main-7.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: How much bond is needed? -earlyAdoption: false ---- - -The initial bond requirement for the first validator for the testnet is 2 stETH. However, for [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), this amount is reduced to 1.5 stETH to incentivize early participation. - -Subsequent bond amounts depend on the total number of validators operated by the node operator and follow a specific function known as the “[bond curve](https://operatorportal.lido.fi/modules/community-staking-module#block-2d1c307d95fc4f8ab7c32b7584f795cf)”, which adjusts the bond requirement based on the operator's validator count. - -For the testnet, the values for the bond curve are the following: - -![curve.png](/assets/curve-common.png) diff --git a/faq/testnet-main-7a.md b/faq/testnet-main-7a.md deleted file mode 100644 index fd008e98c..000000000 --- a/faq/testnet-main-7a.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: How much bond is needed? -earlyAdoption: true ---- - -The initial bond requirement for the first validator for the testnet is 2 stETH. However, for [Early Adopters](https://operatorportal.lido.fi/modules/community-staking-module#block-ef60a1fa96ae4c7995dd7794de2a3e22), this amount is reduced to 1.5 stETH to incentivize early participation. - -Subsequent bond amounts depend on the total number of validators operated by the node operator and follow a specific function known as the “[bond curve](https://operatorportal.lido.fi/modules/community-staking-module#block-2d1c307d95fc4f8ab7c32b7584f795cf)”, which adjusts the bond requirement based on the operator's validator count. - -For the testnet, the values for the bond curve are the following: - -![curve.png](/assets/curve-ea.png) diff --git a/faq/testnet-main-8.md b/faq/testnet-main-8.md deleted file mode 100644 index 35c06f549..000000000 --- a/faq/testnet-main-8.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: How can I get help? ---- - -For community assistance, join the "[CSM-testnet](https://discord.com/channels/761182643269795850/1255114351120089148)" channel on the [Lido Discord server](https://discord.com/invite/lido) to seek advice and guidance. diff --git a/faq/testnet-roles-1.md b/faq/testnet-roles-1.md deleted file mode 100644 index 430183f79..000000000 --- a/faq/testnet-roles-1.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: What are rewards and Manager Addresses? ---- - -There are two addresses associated with your Node Operator that have different scope of responsibilities for managing your Node Operator. - -The Rewards Address is used for: - -- Claiming bond and rewards -- Adding extra bond amount -- Proposing a new Rewards Address -- Resetting the Manager Address to the current Rewards Address - -The Manager Address is used for: - -- Adding new keys -- Removing existing keys -- Adding extra bond amount -- Claiming bond and rewards to the Rewards Address -- Covering locked bond -- Proposing a new Manager Address - -Read more about addresses management [here](https://operatorportal.lido.fi/modules/community-staking-module#block-d3ad2b2bd3994a06b19dccc0794ac8d6). diff --git a/faq/testnet-roles-2.md b/faq/testnet-roles-2.md deleted file mode 100644 index 348752d1d..000000000 --- a/faq/testnet-roles-2.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Why should these addresses be different? ---- - -It's recommended to use different addresses for security reasons. For example, a hot wallet may be used for the Manager Address to simplify daily operations, while a cold wallet (or something like a Safe) is preferable for the Rewards Address to enhance security. - -Read more about addresses management [here](https://operatorportal.lido.fi/modules/community-staking-module#block-d3ad2b2bd3994a06b19dccc0794ac8d6). diff --git a/faq/testnet-roles-3.md b/faq/testnet-roles-3.md deleted file mode 100644 index 893ec2914..000000000 --- a/faq/testnet-roles-3.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: How to accept a change in address request? ---- - -To accept a change in address request, connect to the CSM widget with the new address, navigate to the "Roles" → "Inbox requests" tab, select and accept the request, and confirm the transaction in your wallet. Changes are made once the transaction is processed. diff --git a/faq/testnet-roles-4.md b/faq/testnet-roles-4.md deleted file mode 100644 index 1734995e6..000000000 --- a/faq/testnet-roles-4.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: What to do if the change is submitted to a wrong address? ---- - -If a role change was submitted to the wrong address, the change can be revoked. For Rewards Address changes, navigate to "Roles" → "Rewards Address" → "Revoke". For Manager Address changes, go to "Roles" → "Manager Address" → "Revoke" diff --git a/faq/testnet-roles-5.md b/faq/testnet-roles-5.md deleted file mode 100644 index 90b335a54..000000000 --- a/faq/testnet-roles-5.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: What happens to rewards after changing the Rewards Address? ---- - -Rewards claimed to the previous Rewards Address remain there. After changing the Rewards Address, all rewards and excess bond accumulated on the bond balance can be claimed to the new Rewards Address. In the event of validator withdrawal, upon claiming of the bond, it would also be returned to the new Rewards Address. diff --git a/features/accept-invite/accept-invite-form/accept-invite-form-loader.tsx b/features/accept-invite/accept-invite-form/accept-invite-form-loader.tsx index 23ecc8613..ca99fa747 100644 --- a/features/accept-invite/accept-invite-form/accept-invite-form-loader.tsx +++ b/features/accept-invite/accept-invite-form/accept-invite-form-loader.tsx @@ -1,19 +1,34 @@ +import { Text } from '@lidofinance/lido-ui'; import { FC, PropsWithChildren } from 'react'; -import { useFormState } from 'react-hook-form'; -import { WhenLoaded } from 'shared/components'; -import { AcceptInviteFormInputType, useAcceptInviteFormData } from './context'; +import styled from 'styled-components'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useAcceptInviteFormData } from './context'; + +const CenteredText = styled(Text)` + text-align: center; +`; export const AcceptInviteFormLoader: FC = ({ children }) => { - const { isLoading } = useFormState(); - const { loading, invites } = useAcceptInviteFormData(); - const isEmpty = !invites?.length; + const data = useAcceptInviteFormData(); + const isEmpty = !data.invites?.length; return ( - + + No pending requests + + + When this wallet is proposed as a new Manager or Rewards address, + the request will appear here for you to review and accept + + + ) + } > {children} - + ); }; diff --git a/features/accept-invite/accept-invite-form/accept-invite-form.tsx b/features/accept-invite/accept-invite-form/accept-invite-form.tsx index 4ab778f4b..6e07be665 100644 --- a/features/accept-invite/accept-invite-form/accept-invite-form.tsx +++ b/features/accept-invite/accept-invite-form/accept-invite-form.tsx @@ -1,24 +1,26 @@ import { FC, memo } from 'react'; import { AcceptInviteFormInfo } from './accept-invite-form-info'; -import { AcceptInviteFormProvider } from './context'; +import { AcceptInviteDataProvider, AcceptInviteFormProvider } from './context'; import { InviteSelector } from './controls/invite-selector'; import { SubmitButton } from './controls/submit-button'; import { FormBlock } from 'shared/components'; -import { FormControllerStyled } from 'shared/hook-form/form-controller'; +import { Form } from 'shared/hook-form/form-controller'; import { AcceptInviteFormLoader } from './accept-invite-form-loader'; export const AcceptInviteForm: FC = memo(() => { return ( - - - - - - - - - - - + + + + +
+ + + + +
+
+
+
); }); diff --git a/features/accept-invite/accept-invite-form/context/accept-invite-data-provider.tsx b/features/accept-invite/accept-invite-form/context/accept-invite-data-provider.tsx new file mode 100644 index 000000000..0fa034c44 --- /dev/null +++ b/features/accept-invite/accept-invite-form/context/accept-invite-data-provider.tsx @@ -0,0 +1,59 @@ +import { + KEY_INVITES, + KEY_OPERATOR_INFO, + useDappStatus, + useInvites, + useNodeOperatorId, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import invariant from 'tiny-invariant'; +import { type AcceptInviteFormNetworkData } from './types'; + +const useAcceptInviteFormNetworkData: NetworkData< + AcceptInviteFormNetworkData +> = () => { + const nodeOperatorId = useNodeOperatorId(); + const { address } = useDappStatus(); + const invitesQuery = useInvites(); + + const invites = invitesQuery.data; + const isInvitesLoading = invitesQuery.isPending; + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([KEY_INVITES, KEY_OPERATOR_INFO]); + }, [invalidate]); + + invariant(address); + + return { + data: { + nodeOperatorId, + invites, + address, + } as AcceptInviteFormNetworkData, + isPending: isInvitesLoading, + revalidate, + }; +}; + +export const useAcceptInviteFormData = useFormData; + +export const AcceptInviteDataProvider: FC = ({ + children, +}) => { + const networkData = useAcceptInviteFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/accept-invite/accept-invite-form/context/accept-invite-form-provider.tsx b/features/accept-invite/accept-invite-form/context/accept-invite-form-provider.tsx index a5da8fdff..328e63d28 100644 --- a/features/accept-invite/accept-invite-form/context/accept-invite-form-provider.tsx +++ b/features/accept-invite/accept-invite-form/context/accept-invite-form-provider.tsx @@ -1,57 +1,42 @@ -import { FC, PropsWithChildren, useMemo } from 'react'; +import { FC, PropsWithChildren } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormControllerRetry, - useFormData, + FormControllerProvider, + useFlowSubmit, + useFormDefaultValues, } from 'shared/hook-form/form-controller'; import { AcceptInviteFormNetworkData, type AcceptInviteFormInputType, } from './types'; -import { useAcceptInviteFormNetworkData } from './use-accept-invite-form-network-data'; -import { useAcceptInviteSubmit } from './use-accept-invite-submit'; -import { useGetDefaultValues } from './use-get-default-values'; - -export const useAcceptInviteFormData = useFormData; +import { useAcceptInviteFlowResolver } from './use-accept-invite-flow'; +import { useAcceptInviteValidation } from './use-accept-invite-validation'; export const AcceptInviteFormProvider: FC = ({ children, }) => { - const [networkData, revalidate] = useAcceptInviteFormNetworkData(); + const defaultValues = useFormDefaultValues< + AcceptInviteFormInputType, + AcceptInviteFormNetworkData + >((data) => ({ + invite: data.invites[0], + })); - const asyncDefaultValues = useGetDefaultValues(networkData); + const resolver = useAcceptInviteValidation(); const formObject = useForm({ - defaultValues: asyncDefaultValues, + defaultValues, mode: 'onChange', + resolver, }); - const { retryEvent, retryFire } = useFormControllerRetry(); - - const { acceptInvite } = useAcceptInviteSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType = - useMemo( - () => ({ - onSubmit: acceptInvite, - retryEvent, - }), - [acceptInvite, retryEvent], - ); + const submitter = useFlowSubmit(useAcceptInviteFlowResolver()); return ( - - - {children} - - + + {children} + ); }; diff --git a/features/accept-invite/accept-invite-form/context/index.ts b/features/accept-invite/accept-invite-form/context/index.ts index 6ff4589ea..48bfe379c 100644 --- a/features/accept-invite/accept-invite-form/context/index.ts +++ b/features/accept-invite/accept-invite-form/context/index.ts @@ -1,2 +1,3 @@ +export * from './accept-invite-data-provider'; export * from './accept-invite-form-provider'; export * from './types'; diff --git a/features/accept-invite/accept-invite-form/context/types.ts b/features/accept-invite/accept-invite-form/context/types.ts index 3410e3378..1ddcedc20 100644 --- a/features/accept-invite/accept-invite-form/context/types.ts +++ b/features/accept-invite/accept-invite-form/context/types.ts @@ -1,12 +1,15 @@ -import { Address } from 'wagmi'; -import { LoadingRecord, NodeOperatorInvite } from 'types'; +import { + NodeOperatorId, + NodeOperatorInviteInfo, +} from '@lidofinance/lido-csm-sdk'; +import { Address } from 'viem'; export type AcceptInviteFormInputType = { - invite?: NodeOperatorInvite; + invite?: NodeOperatorInviteInfo; }; export type AcceptInviteFormNetworkData = { - invites?: NodeOperatorInvite[]; + nodeOperatorId?: NodeOperatorId; + invites: NodeOperatorInviteInfo[]; address: Address; - loading: LoadingRecord<'invites'>; }; diff --git a/features/accept-invite/accept-invite-form/context/use-accept-invite-flow.ts b/features/accept-invite/accept-invite-form/context/use-accept-invite-flow.ts new file mode 100644 index 000000000..aef9ef72d --- /dev/null +++ b/features/accept-invite/accept-invite-form/context/use-accept-invite-flow.ts @@ -0,0 +1,65 @@ +import { useCallback } from 'react'; + +import { PATH } from 'consts/urls'; +import { useAppendOperator, useSmSDK } from 'modules/web3'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useNavigate } from 'shared/navigate'; +import invariant from 'tiny-invariant'; +import { useTxModalStagesAcceptInvite } from '../hooks/use-tx-modal-stages-accept-invite'; +import { useAcceptInviteFormData } from './accept-invite-data-provider'; +import { + AcceptInviteFormInputType, + AcceptInviteFormNetworkData, +} from './types'; + +export type AcceptInviteFlow = + | { action: 'no-invite' } + | ({ action: 'accept' } & Executable); + +export const useAcceptInviteFlowResolver = (): FlowResolver< + AcceptInviteFormInputType, + AcceptInviteFormNetworkData, + AcceptInviteFlow +> => { + const sdk = useSmSDK(); + const appendNO = useAppendOperator(); + const n = useNavigate(); + const buildCallback = useTxModalStagesAcceptInvite(); + + return useCallback( + (input, data) => { + if (!input.invite) return { action: 'no-invite' }; + + const invite = input.invite; + + return { + action: 'accept' as const, + submit: async () => { + invariant(invite !== undefined, 'Invite is not defined'); + + const { result } = await sdk.roles.confirmAddress({ + nodeOperatorId: invite.nodeOperatorId, + role: invite.role, + callback: buildCallback(input, data), + }); + + if (result) appendNO(result); + + if (data.nodeOperatorId === undefined && data.invites.length <= 1) { + void n(PATH.HOME); + } + }, + }; + }, + [sdk.roles, appendNO, n, buildCallback], + ); +}; + +export const useAcceptInviteFlow = (): AcceptInviteFlow => { + const resolve = useAcceptInviteFlowResolver(); + const data = useAcceptInviteFormData(true); + return resolve({} as AcceptInviteFormInputType, data); +}; diff --git a/features/accept-invite/accept-invite-form/context/use-accept-invite-form-network-data.tsx b/features/accept-invite/accept-invite-form/context/use-accept-invite-form-network-data.tsx deleted file mode 100644 index d8de44ec1..000000000 --- a/features/accept-invite/accept-invite-form/context/use-accept-invite-form-network-data.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useCallback, useMemo } from 'react'; -import { useAccount, useInvites } from 'shared/hooks'; -import { type AcceptInviteFormNetworkData } from './types'; -import invariant from 'tiny-invariant'; - -export const useAcceptInviteFormNetworkData = (): [ - AcceptInviteFormNetworkData, - () => Promise, -] => { - const { address } = useAccount(); - const { - data: invites, - initialLoading: isInvitesLoading, - update: updateInvites, - } = useInvites(); - - const revalidate = useCallback(async () => { - await Promise.allSettled([updateInvites()]); - }, [updateInvites]); - - const loading = useMemo( - () => ({ - isInvitesLoading, - }), - [isInvitesLoading], - ); - - invariant(address); - - return [ - { - invites, - address, - loading, - }, - revalidate, - ]; -}; diff --git a/features/accept-invite/accept-invite-form/context/use-accept-invite-submit.ts b/features/accept-invite/accept-invite-form/context/use-accept-invite-submit.ts deleted file mode 100644 index e742e68c3..000000000 --- a/features/accept-invite/accept-invite-form/context/use-accept-invite-submit.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { useCallback } from 'react'; -import invariant from 'tiny-invariant'; - -import { ROLES } from 'consts/roles'; -import { useNodeOperatorContext } from 'providers/node-operator-provider'; -import { useCSModuleWeb3, useSendTx } from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; -import { runWithTransactionLogger } from 'utils'; -import { useTxModalStagesAcceptInvite } from '../hooks/use-tx-modal-stages-accept-invite'; -import { - AcceptInviteFormInputType, - AcceptInviteFormNetworkData, -} from './types'; - -// TODO: move to hooks -type UseAcceptInviteOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type AcceptInviteMethodParams = { - nodeOperatorId: NodeOperatorId; -}; - -// encapsulates eth/steth/wsteth flows -const useAcceptInviteTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async (role: ROLES, params: AcceptInviteMethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - switch (role) { - case ROLES.MANAGER: - return { - tx: await CSModuleWeb3.populateTransaction.confirmNodeOperatorManagerAddressChange( - params.nodeOperatorId, - ), - txName: 'confirmNodeOperatorManagerAddressChange', - }; - case ROLES.REWARDS: - return { - tx: await CSModuleWeb3.populateTransaction.confirmNodeOperatorRewardAddressChange( - params.nodeOperatorId, - ), - txName: 'confirmNodeOperatorRewardAddressChange', - }; - } - }, - [CSModuleWeb3], - ); -}; - -export const useAcceptInviteSubmit = ({ - onConfirm, - onRetry, -}: UseAcceptInviteOptions) => { - const { txModalStages } = useTxModalStagesAcceptInvite(); - const { append: appendNO } = useNodeOperatorContext(); - - const getTx = useAcceptInviteTx(); - const sendTx = useSendTx(); - - const acceptInvite = useCallback( - async ( - { invite }: AcceptInviteFormInputType, - { address }: AcceptInviteFormNetworkData, - ): Promise => { - invariant(invite, 'Invite is not defined'); - - try { - txModalStages.sign(invite); - - const tx = await getTx(invite.role, { - nodeOperatorId: invite.id, - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'AcceptInvite signing', - () => sendTx(tx), - ); - - txModalStages.pending(invite, txHash); - - if (typeof tx === 'object') { - await runWithTransactionLogger( - 'AcceptInvite block confirmation', - waitTx, - ); - } - - await onConfirm?.(); - - txModalStages.success({ ...invite, address }, txHash); - - // TODO: move to onConfirm - appendNO(invite); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [getTx, txModalStages, onConfirm, appendNO, sendTx, onRetry], - ); - - return { - acceptInvite, - }; -}; diff --git a/features/accept-invite/accept-invite-form/context/use-accept-invite-validation.ts b/features/accept-invite/accept-invite-form/context/use-accept-invite-validation.ts new file mode 100644 index 000000000..abb7beee1 --- /dev/null +++ b/features/accept-invite/accept-invite-form/context/use-accept-invite-validation.ts @@ -0,0 +1,19 @@ +import { + useFormValidation, + ValidationError, +} from 'shared/hook-form/validation'; +import type { + AcceptInviteFormInputType, + AcceptInviteFormNetworkData, +} from './types'; + +export const useAcceptInviteValidation = () => { + return useFormValidation< + AcceptInviteFormInputType, + AcceptInviteFormNetworkData + >('invite', async ({ invite }) => { + if (!invite) { + throw new ValidationError('invite', 'Please select an invite'); + } + }); +}; diff --git a/features/accept-invite/accept-invite-form/context/use-get-default-values.tsx b/features/accept-invite/accept-invite-form/context/use-get-default-values.tsx deleted file mode 100644 index 44d837675..000000000 --- a/features/accept-invite/accept-invite-form/context/use-get-default-values.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { useCallback, useMemo } from 'react'; -import { useAwaiter } from 'shared/hooks'; -import { - AcceptInviteFormInputType, - AcceptInviteFormNetworkData, -} from './types'; - -export const useGetDefaultValues = ({ - invites, - loading: { isInvitesLoading }, -}: AcceptInviteFormNetworkData) => { - const values: AcceptInviteFormInputType | undefined = useMemo(() => { - if (isInvitesLoading) return undefined; - return { invite: invites?.[0] }; - }, [invites, isInvitesLoading]); - - const { awaiter } = useAwaiter(values); - - return useCallback(() => awaiter, [awaiter]); -}; diff --git a/features/accept-invite/accept-invite-form/controls/invite-selector.tsx b/features/accept-invite/accept-invite-form/controls/invite-selector.tsx index 9151f5517..884eafa67 100644 --- a/features/accept-invite/accept-invite-form/controls/invite-selector.tsx +++ b/features/accept-invite/accept-invite-form/controls/invite-selector.tsx @@ -1,14 +1,20 @@ +import { Text } from '@lidofinance/lido-ui'; import { FormTitle } from 'shared/components'; import { InviteButtonsHookForm } from 'shared/hook-form/controls'; import { useAcceptInviteFormData } from '../context'; export const InviteSelector = () => { - const { invites } = useAcceptInviteFormData(); + const { invites } = useAcceptInviteFormData(true); return ( <> Choose request to accept - + + This section shows pending requests to assign this wallet as a Manager + or Rewards address for a Node Operator. Select a request and accept it + by signing a transaction. + + ); }; diff --git a/features/accept-invite/accept-invite-form/controls/submit-button.tsx b/features/accept-invite/accept-invite-form/controls/submit-button.tsx index 610ec738d..46a0b563a 100644 --- a/features/accept-invite/accept-invite-form/controls/submit-button.tsx +++ b/features/accept-invite/accept-invite-form/controls/submit-button.tsx @@ -1,9 +1,5 @@ import { SubmitButtonHookForm } from 'shared/hook-form/controls'; export const SubmitButton = () => { - return ( - - Accept request - - ); + return Accept request; }; diff --git a/features/accept-invite/accept-invite-form/hooks/use-tx-modal-stages-accept-invite.tsx b/features/accept-invite/accept-invite-form/hooks/use-tx-modal-stages-accept-invite.tsx index 3fa258400..807073430 100644 --- a/features/accept-invite/accept-invite-form/hooks/use-tx-modal-stages-accept-invite.tsx +++ b/features/accept-invite/accept-invite-form/hooks/use-tx-modal-stages-accept-invite.tsx @@ -1,71 +1,84 @@ -import { ROLES } from 'consts/roles'; +import { + type NodeOperatorInviteInfo, + type NodeOperatorShortInfo, +} from '@lidofinance/lido-csm-sdk'; +import { ROLES_METADATA } from 'consts/roles'; import { Address } from 'shared/components'; -import { DescriptorId, getRoleTitle } from 'shared/node-operator'; +import { DescriptorId } from 'shared/node-operator'; import { - TransactionModalTransitStage, + type TransactionModalTransitStage, TxStagePending, TxStageSign, TxStageSuccess, - getGeneralTransactionModalStages, - useTransactionModalStage, + useTxStages, } from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; +import invariant from 'tiny-invariant'; +import { type Address as TAddress } from 'viem'; +import { + AcceptInviteFormInputType, + AcceptInviteFormNetworkData, +} from '../context/types'; -type Props = { id: NodeOperatorId; role: ROLES }; +type AcceptInviteStageParams = { + invite: Pick; + address: TAddress; +}; -const getTxModalStagesAcceptInvite = ( +export const buildAcceptInviteStages = ( transitStage: TransactionModalTransitStage, + { invite, address }: AcceptInviteStageParams, ) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: ({ id, role }: Props) => + sign: () => transitStage( - {getRoleTitle(role)} address + —{' '} + {ROLES_METADATA[invite.role].capitalizedTitle} Address } />, ), - - pending: ({ id, role }: Props, txHash?: string) => + pending: (txHash?: string) => transitStage( - {getRoleTitle(role)} address + —{' '} + {ROLES_METADATA[invite.role].capitalizedTitle} Address } txHash={txHash} />, ), - - // TODO: "go to dashboard" button - success: ( - { id, role, address }: Props & { address: string }, - txHash?: string, - ) => + success: (_result: NodeOperatorShortInfo, txHash?: string) => transitStage( Address change has been accepted} description={ <> - {getRoleTitle(role, true)} address of is + {ROLES_METADATA[invite.role].capitalizedTitle} Address of{' '} + is
} />, - { - isClosableOnLedger: true, - }, ), }); -export const useTxModalStagesAcceptInvite = () => { - return useTransactionModalStage(getTxModalStagesAcceptInvite); -}; +export const useTxModalStagesAcceptInvite = () => + useTxStages< + AcceptInviteFormInputType, + AcceptInviteFormNetworkData, + NodeOperatorShortInfo + >((transitStage, input, data) => { + invariant(input.invite, 'Invite is required'); + return buildAcceptInviteStages(transitStage, { + invite: input.invite, + address: data.address, + }); + }); diff --git a/features/accept-invite/accept-invite-page.tsx b/features/accept-invite/accept-invite-page.tsx index 4355c9e08..50f5d5dda 100644 --- a/features/accept-invite/accept-invite-page.tsx +++ b/features/accept-invite/accept-invite-page.tsx @@ -1,19 +1,21 @@ import { FC } from 'react'; +import { FAQ_ROLES } from 'faq'; +import { Faq } from 'shared/components'; import { Layout } from 'shared/layout'; -import { RolesPageSwitcher } from 'shared/navigate'; +import { SettingsPageSwitcher } from 'shared/navigate'; import { AcceptInvite } from './accept-invite'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; export const AcceptInvitePage: FC = () => { return ( - + + ); }; diff --git a/features/accept-invite/accept-invite.tsx b/features/accept-invite/accept-invite.tsx index 224a94e49..8ce6040ec 100644 --- a/features/accept-invite/accept-invite.tsx +++ b/features/accept-invite/accept-invite.tsx @@ -1,7 +1,6 @@ import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; +import { useWeb3Key } from 'shared/hooks'; import { AcceptInviteForm } from './accept-invite-form'; -import { Faq } from 'shared/components'; export const AcceptInvite = () => { const key = useWeb3Key(); @@ -10,7 +9,6 @@ export const AcceptInvite = () => { - ); }; diff --git a/features/add-bond/add-bond-form/add-bond-form-info.tsx b/features/add-bond/add-bond-form/add-bond-form-info.tsx index c4a942d82..7a884fafa 100644 --- a/features/add-bond/add-bond-form/add-bond-form-info.tsx +++ b/features/add-bond/add-bond-form/add-bond-form-info.tsx @@ -1,12 +1,12 @@ +import { convertSharesToEth, TOKENS } from '@lidofinance/lido-csm-sdk'; import { DataTable, DataTableRow } from '@lidofinance/lido-ui'; -import { ONE_ETH, TOKENS } from 'consts/tokens'; +import { ONE_ETH } from 'consts/tokens'; import { useWatch } from 'react-hook-form'; import { FormatToken } from 'shared/formatters'; -import { AddBondFormInputType } from './context'; -import { useReceiveAmount } from './hooks/use-receive-amount'; -import { useExchangeRate } from 'shared/hooks'; +import { AddBondFormInputType, useAddBondFormData } from './context'; export const AddBondFormInfo = () => { + const { poolData } = useAddBondFormData(true); const [token, bondAmount] = useWatch< AddBondFormInputType, ['token', 'bondAmount'] @@ -14,18 +14,24 @@ export const AddBondFormInfo = () => { name: ['token', 'bondAmount'], }); - const receive = useReceiveAmount(bondAmount, token); - const exchange = useExchangeRate(token); + const toSteth = (amount: bigint) => + token === TOKENS.wsteth ? convertSharesToEth(amount, poolData) : amount; + + const receiveAmount = toSteth(bondAmount ?? 0n); + const rate = toSteth(ONE_ETH); return ( - - - + + + - {token !== TOKENS.STETH && ( - + {token !== TOKENS.steth && ( + ={' '} - + )} diff --git a/features/add-bond/add-bond-form/add-bond-form-loader.tsx b/features/add-bond/add-bond-form/add-bond-form-loader.tsx new file mode 100644 index 000000000..99febab3e --- /dev/null +++ b/features/add-bond/add-bond-form/add-bond-form-loader.tsx @@ -0,0 +1,18 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useAddBondFlow } from './context'; +import { Info } from './controls/info'; + +const AddBondFormGate: FC = ({ children }) => { + const flow = useAddBondFlow(); + + const isReadOnly = flow.action === 'no-access'; + + return isReadOnly ? : <>{children}; +}; + +export const AddBondFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/add-bond/add-bond-form/add-bond-form.tsx b/features/add-bond/add-bond-form/add-bond-form.tsx index 3c027f962..4827d004d 100644 --- a/features/add-bond/add-bond-form/add-bond-form.tsx +++ b/features/add-bond/add-bond-form/add-bond-form.tsx @@ -1,13 +1,11 @@ import { FC, memo } from 'react'; -import { AddBondFormProvider } from './context'; +import { AddBondDataProvider, AddBondFormProvider } from './context'; import { FormBlock } from 'shared/components'; -import { - BaseFormLoader, - FormControllerStyled, -} from 'shared/hook-form/form-controller'; +import { Form } from 'shared/hook-form/form-controller'; import { AddBondFormInfo } from './add-bond-form-info'; +import { AddBondFormLoader } from './add-bond-form-loader'; import { AmountInput } from './controls/amount-input'; import { Info } from './controls/info'; import { SubmitButton } from './controls/submit-button'; @@ -15,18 +13,20 @@ import { TokenSelect } from './controls/token-select'; export const AddBondForm: FC = memo(() => { return ( - - - - - - - - - - - - - + + + + +
+ + + + + + +
+
+
+
); }); diff --git a/features/add-bond/add-bond-form/context/add-bond-data-provider.tsx b/features/add-bond/add-bond-form/context/add-bond-data-provider.tsx new file mode 100644 index 000000000..7f5af69a1 --- /dev/null +++ b/features/add-bond/add-bond-form/context/add-bond-data-provider.tsx @@ -0,0 +1,99 @@ +import { + KEY_OPERATOR_BALANCE, + KEY_STAKE_LIMIT, + useSmStatus, + useEthereumBalance, + useNodeOperatorId, + useOperatorBalance, + useStakeLimit, + useStethBalance, + useStethPoolData, + useWstethBalance, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import { type AddBondFormNetworkData } from './types'; + +const useAddBondFormNetworkData: NetworkData = () => { + const nodeOperatorId = useNodeOperatorId(); + + const ethBalanceQuery = useEthereumBalance(); + const stethBalanceQuery = useStethBalance(); + const wstethBalanceQuery = useWstethBalance(); + const bondQuery = useOperatorBalance(nodeOperatorId); + const maxStakeEthQuery = useStakeLimit(); + + const ethBalance = ethBalanceQuery.data; + const stethBalance = stethBalanceQuery.data; + const wstethBalance = wstethBalanceQuery.data; + const bond = bondQuery.data; + const maxStakeEth = maxStakeEthQuery.data; + + const isEthBalanceLoading = ethBalanceQuery.isPending; + const isStethBalanceLoading = stethBalanceQuery.isPending; + const isWstethBalanceLoading = wstethBalanceQuery.isPending; + const isBondLoading = bondQuery.isPending; + const isMaxStakeEthLoading = maxStakeEthQuery.isPending; + + const { data: poolData, isPending: isPoolDataLoading } = useStethPoolData(); + + const { data: status, isPending: isStatusLoading } = useSmStatus(); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ + ethBalanceQuery.queryKey, + stethBalanceQuery.queryKey, + wstethBalanceQuery.queryKey, + KEY_OPERATOR_BALANCE, + KEY_STAKE_LIMIT, + ]); + }, [ + invalidate, + ethBalanceQuery.queryKey, + stethBalanceQuery.queryKey, + wstethBalanceQuery.queryKey, + ]); + + const isPending = + isEthBalanceLoading || + isStethBalanceLoading || + isWstethBalanceLoading || + isBondLoading || + isMaxStakeEthLoading || + isPoolDataLoading || + isStatusLoading; + + return { + data: { + nodeOperatorId, + ethBalance, + stethBalance, + wstethBalance, + bond, + maxStakeEth, + poolData, + isPaused: status?.isPausedAccounting, + } as AddBondFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useAddBondFormData = useFormData; + +export const AddBondDataProvider: FC = ({ children }) => { + const networkData = useAddBondFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/add-bond/add-bond-form/context/add-bond-form-provider.tsx b/features/add-bond/add-bond-form/context/add-bond-form-provider.tsx index fbe094415..de279ab94 100644 --- a/features/add-bond/add-bond-form/context/add-bond-form-provider.tsx +++ b/features/add-bond/add-bond-form/context/add-bond-form-provider.tsx @@ -1,59 +1,33 @@ -import { FC, PropsWithChildren, useMemo } from 'react'; +import { FC, PropsWithChildren } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormControllerRetry, - useFormData, + FormControllerProvider, + useFlowSubmit, } from 'shared/hook-form/form-controller'; -import { AddBondFormNetworkData, type AddBondFormInputType } from './types'; -import { useAddBondFormNetworkData } from './use-add-bond-form-network-data'; -import { useAddBondSubmit } from './use-add-bond-submit'; +import { AddBondUpdater } from './add-bond-updater'; +import { type AddBondFormInputType } from './types'; +import { useAddBondDefaultValues } from './use-add-bond-default-values'; +import { useAddBondFlowResolver } from './use-add-bond-flow'; import { useAddBondValidation } from './use-add-bond-validation'; -import { useFormRevalidate } from './use-form-revalidate'; -import { useGetDefaultValues } from './use-get-default-values'; - -export const useAddBondFormData = useFormData; export const AddBondFormProvider: FC = ({ children }) => { - const [networkData, revalidate] = useAddBondFormNetworkData(); - const validationResolver = useAddBondValidation(networkData); - const asyncDefaultValues = useGetDefaultValues(networkData); + const resolver = useAddBondValidation(); + const defaultValues = useAddBondDefaultValues(); const formObject = useForm({ - defaultValues: asyncDefaultValues, - resolver: validationResolver, + defaultValues, + resolver, mode: 'onChange', }); - useFormRevalidate(formObject); - - const { retryEvent, retryFire } = useFormControllerRetry(); - - const { addBond } = useAddBondSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - AddBondFormInputType, - AddBondFormNetworkData - > = useMemo( - () => ({ - onSubmit: addBond, - retryEvent, - }), - [addBond, retryEvent], - ); + const submitter = useFlowSubmit(useAddBondFlowResolver()); return ( - - - {children} - - + + + {children} + ); }; diff --git a/features/add-bond/add-bond-form/context/add-bond-updater.tsx b/features/add-bond/add-bond-form/context/add-bond-updater.tsx new file mode 100644 index 000000000..6decf5040 --- /dev/null +++ b/features/add-bond/add-bond-form/context/add-bond-updater.tsx @@ -0,0 +1,19 @@ +import { FC, useEffect } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { AddBondFormInputType } from './types'; + +export const AddBondUpdater: FC = () => { + const [token] = useWatch({ + name: ['token'], + }); + + const { trigger } = useFormContext(); + + useEffect(() => { + void trigger('bondAmount'); + // trigger is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [token]); + + return null; +}; diff --git a/features/add-bond/add-bond-form/context/index.ts b/features/add-bond/add-bond-form/context/index.ts index 265faa461..a6d3f9621 100644 --- a/features/add-bond/add-bond-form/context/index.ts +++ b/features/add-bond/add-bond-form/context/index.ts @@ -1,2 +1,4 @@ export * from './add-bond-form-provider'; +export * from './add-bond-data-provider'; export * from './types'; +export * from './use-add-bond-flow'; diff --git a/features/add-bond/add-bond-form/context/types.ts b/features/add-bond/add-bond-form/context/types.ts index 501894f95..9bfec9644 100644 --- a/features/add-bond/add-bond-form/context/types.ts +++ b/features/add-bond/add-bond-form/context/types.ts @@ -1,26 +1,22 @@ -import { BigNumber } from 'ethers'; -import { type TOKENS } from 'consts/tokens'; -import { BondBalance, LoadingRecord, NodeOperatorId } from 'types'; +import { + BondBalance, + NodeOperatorId, + StethPoolData, + TOKENS, +} from '@lidofinance/lido-csm-sdk'; export type AddBondFormInputType = { token: TOKENS; - bondAmount?: BigNumber; + bondAmount?: bigint; }; export type AddBondFormNetworkData = { - nodeOperatorId?: NodeOperatorId; - etherBalance?: BigNumber; - stethBalance?: BigNumber; - wstethBalance?: BigNumber; - bond?: BondBalance; - maxStakeEther?: BigNumber | null; - isPaused?: boolean; - loading: LoadingRecord< - | 'etherBalance' - | 'stethBalance' - | 'wstethBalance' - | 'bond' - | 'maxStakeEther' - | 'status' - >; + nodeOperatorId: NodeOperatorId; + ethBalance: bigint; + stethBalance: bigint; + wstethBalance: bigint; + bond: BondBalance; + maxStakeEth: bigint; + poolData: StethPoolData; + isPaused: boolean; }; diff --git a/features/add-bond/add-bond-form/context/use-add-bond-default-values.ts b/features/add-bond/add-bond-form/context/use-add-bond-default-values.ts new file mode 100644 index 000000000..39c4af454 --- /dev/null +++ b/features/add-bond/add-bond-form/context/use-add-bond-default-values.ts @@ -0,0 +1,16 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { getMaxBalanceToken } from 'modules/web3'; +import { useFormDefaultValues } from 'shared/hook-form/form-controller'; +import { AddBondFormInputType, AddBondFormNetworkData } from './types'; + +export const useAddBondDefaultValues = () => { + return useFormDefaultValues( + (data) => ({ + token: getMaxBalanceToken({ + [TOKENS.eth]: data.ethBalance, + [TOKENS.steth]: data.stethBalance, + [TOKENS.wsteth]: data.wstethBalance, + }), + }), + ); +}; diff --git a/features/add-bond/add-bond-form/context/use-add-bond-flow.ts b/features/add-bond/add-bond-form/context/use-add-bond-flow.ts new file mode 100644 index 000000000..c25514afa --- /dev/null +++ b/features/add-bond/add-bond-form/context/use-add-bond-flow.ts @@ -0,0 +1,57 @@ +import { type MethodAccess } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useCanPerform } from 'shared/hooks'; +import invariant from 'tiny-invariant'; +import { useTxModalStagesAddBond } from '../hooks/use-tx-modal-stages-add-bond'; +import { useAddBondFormData } from './add-bond-data-provider'; +import { AddBondFormInputType, AddBondFormNetworkData } from './types'; + +export type AddBondFlow = + | { action: 'no-access'; access: MethodAccess } + | { action: 'paused' } + | ({ action: 'add-bond' } & Executable); + +export const useAddBondFlowResolver = (): FlowResolver< + AddBondFormInputType, + AddBondFormNetworkData, + AddBondFlow +> => { + const { bond: bondSDK } = useSmSDK(); + const [canAddBond, addBondAccess] = useCanPerform(bondSDK, 'addBond'); + const buildCallback = useTxModalStagesAddBond(); + + return useCallback( + (input, data) => { + if (!canAddBond) return { action: 'no-access', access: addBondAccess }; + if (data.isPaused) return { action: 'paused' }; + + return { + action: 'add-bond' as const, + submit: () => { + invariant( + input.bondAmount !== undefined, + 'BondAmount is not defined', + ); + return bondSDK.addBond({ + nodeOperatorId: data.nodeOperatorId, + token: input.token, + amount: input.bondAmount, + callback: buildCallback(input, data), + }); + }, + }; + }, + [bondSDK, canAddBond, addBondAccess, buildCallback], + ); +}; + +export const useAddBondFlow = (): AddBondFlow => { + const resolve = useAddBondFlowResolver(); + const data = useAddBondFormData(true); + return resolve({} as AddBondFormInputType, data); +}; diff --git a/features/add-bond/add-bond-form/context/use-add-bond-form-network-data.tsx b/features/add-bond/add-bond-form/context/use-add-bond-form-network-data.tsx deleted file mode 100644 index 3326d00e4..000000000 --- a/features/add-bond/add-bond-form/context/use-add-bond-form-network-data.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { - useEthereumBalance, - useSTETHBalance, - useWSTETHBalance, -} from '@lido-sdk/react'; -import { STRATEGY_LAZY } from 'consts/swr-strategies'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { useCallback, useMemo } from 'react'; -import { - useCsmPaused, - useNodeOperatorBalance, - useStakingLimitInfo, -} from 'shared/hooks'; -import { type AddBondFormNetworkData } from '../context/types'; - -export const useAddBondFormNetworkData = (): [ - AddBondFormNetworkData, - () => Promise, -] => { - const nodeOperatorId = useNodeOperatorId(); - const { - data: etherBalance, - update: updateEtherBalance, - initialLoading: isEtherBalanceLoading, - } = useEthereumBalance(undefined, STRATEGY_LAZY); - const { - data: stethBalance, - update: updateStethBalance, - initialLoading: isStethBalanceLoading, - } = useSTETHBalance(STRATEGY_LAZY); - const { - data: wstethBalance, - update: updateWstethBalance, - initialLoading: isWstethBalanceLoading, - } = useWSTETHBalance(STRATEGY_LAZY); - const { - data: bond, - update: updateBond, - initialLoading: isBondLoading, - } = useNodeOperatorBalance(nodeOperatorId); - const { - data: maxStakeEther, - update: updateMaxStakeEther, - initialLoading: isMaxStakeEtherLoading, - } = useStakingLimitInfo(); - - const { data: status, initialLoading: isStatusLoading } = useCsmPaused(); - - const revalidate = useCallback(async () => { - await Promise.allSettled([ - updateStethBalance(), - updateWstethBalance(), - updateEtherBalance(), - updateBond(), - updateMaxStakeEther(), - ]); - }, [ - updateStethBalance, - updateWstethBalance, - updateEtherBalance, - updateBond, - updateMaxStakeEther, - ]); - - const loading = useMemo( - () => ({ - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - isBondLoading, - isMaxStakeEtherLoading, - isStatusLoading, - }), - [ - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - isBondLoading, - isMaxStakeEtherLoading, - isStatusLoading, - ], - ); - - return [ - { - etherBalance, - stethBalance, - wstethBalance, - bond, - nodeOperatorId, - maxStakeEther, - isPaused: status?.isAccountingPaused, - loading, - }, - revalidate, - ]; -}; diff --git a/features/add-bond/add-bond-form/context/use-add-bond-submit.ts b/features/add-bond/add-bond-form/context/use-add-bond-submit.ts deleted file mode 100644 index b4449e3a1..000000000 --- a/features/add-bond/add-bond-form/context/use-add-bond-submit.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { BigNumber } from 'ethers'; -import { useCallback } from 'react'; -import invariant from 'tiny-invariant'; - -import { TOKENS } from 'consts/tokens'; -import { - useCSAccountingRPC, - useCSModuleWeb3, - usePermitOrApprove, - useSendTx, -} from 'shared/hooks'; -import { GatherPermitSignatureResult } from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; -import { addExtraWei, runWithTransactionLogger } from 'utils'; -import { AddBondFormInputType, AddBondFormNetworkData } from '../context'; -import { useTxModalStagesAddBond } from '../hooks/use-tx-modal-stages-add-bond'; - -type UseAddBondOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type AddBondMethodParams = { - amount: BigNumber; - permit: GatherPermitSignatureResult; - nodeOperatorId: NodeOperatorId; -}; - -// encapsulates eth/steth/wsteth flows -const useAddBondTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async (token: TOKENS, params: AddBondMethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - switch (token) { - case TOKENS.ETH: - return { - tx: await CSModuleWeb3.populateTransaction.depositETH( - params.nodeOperatorId, - { - value: params.amount, - }, - ), - txName: 'depositETH', - }; - case TOKENS.STETH: - return { - tx: await CSModuleWeb3.populateTransaction.depositStETH( - params.nodeOperatorId, - params.amount, - params.permit, - ), - txName: 'depositStETH', - }; - case TOKENS.WSTETH: - return { - tx: await CSModuleWeb3.populateTransaction.depositWstETH( - params.nodeOperatorId, - params.amount, - params.permit, - ), - txName: 'depositWstETH', - }; - } - }, - [CSModuleWeb3], - ); -}; - -export const useAddBondSubmit = ({ onConfirm, onRetry }: UseAddBondOptions) => { - const { txModalStages } = useTxModalStagesAddBond(); - const CSAccounting = useCSAccountingRPC(); - - const getTx = useAddBondTx(); - const sendTx = useSendTx(); - const getPermitOrApprove = usePermitOrApprove(); - - const addBond = useCallback( - async ( - { bondAmount: amount, token }: AddBondFormInputType, - { nodeOperatorId }: AddBondFormNetworkData, - ): Promise => { - invariant(token, 'Token is not defined'); - invariant(amount, 'BondAmount is not defined'); - invariant(nodeOperatorId, 'NodeOperatorId is not defined'); - - try { - const { permit } = await getPermitOrApprove({ - token, - amount: addExtraWei(amount, token), - txModalStages, - }); - - txModalStages.sign({ amount, token }); - - const tx = await getTx(token, { - nodeOperatorId, - amount, - permit, - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'AddBond signing', - () => sendTx(tx), - ); - - txModalStages.pending({ amount, token }, txHash); - - await runWithTransactionLogger('AddBond block confirmation', waitTx); - - // TODO: move to onConfirm - const { current } = await CSAccounting.getBondSummary(nodeOperatorId); - - await onConfirm?.(); - - txModalStages.success({ balance: current }, txHash); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [ - getTx, - getPermitOrApprove, - txModalStages, - CSAccounting, - onConfirm, - sendTx, - onRetry, - ], - ); - - return { - addBond, - }; -}; diff --git a/features/add-bond/add-bond-form/context/use-add-bond-validation.ts b/features/add-bond/add-bond-form/context/use-add-bond-validation.ts index b2f52c936..63c048c38 100644 --- a/features/add-bond/add-bond-form/context/use-add-bond-validation.ts +++ b/features/add-bond/add-bond-form/context/use-add-bond-validation.ts @@ -1,42 +1,32 @@ -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; import { - handleResolverValidationError, + useFormValidation, validateBondAmount, validateEtherAmount, } from 'shared/hook-form/validation'; -import { useAwaitNetworkData } from 'shared/hooks'; import type { AddBondFormInputType, AddBondFormNetworkData } from './types'; +// import invaria t from 'tiny-invariant'; -export const useAddBondValidation = (networkData: AddBondFormNetworkData) => { - const dataPromise = useAwaitNetworkData(networkData); - - return useCallback>( - async (values) => { - try { - const { token, bondAmount } = values; - - const { stethBalance, wstethBalance, etherBalance, maxStakeEther } = - await dataPromise; +export const useAddBondValidation = () => { + return useFormValidation( + 'token', + async ({ token, bondAmount }, data, validate) => { + // invariant(token !== undefined, 'Token is not defined'); + // invariant(bondAmount !== undefined, 'BondAmount is not defined'); + await validate(['token', 'bondAmount'], () => validateBondAmount({ token, bondAmount, - maxStakeEther, - etherBalance, - stethBalance, - wstethBalance, - }); - validateEtherAmount('bondAmount', bondAmount, token); + maxStakeEth: data.maxStakeEth, + ethBalance: data.ethBalance, + stethBalance: data.stethBalance, + wstethBalance: data.wstethBalance, + }), + ); - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError(error, 'AddBondForm', 'token'); - } + await validate('bondAmount', () => + validateEtherAmount('bondAmount', bondAmount, token), + ); }, - [dataPromise], ); }; diff --git a/features/add-bond/add-bond-form/context/use-form-revalidate.ts b/features/add-bond/add-bond-form/context/use-form-revalidate.ts deleted file mode 100644 index fa69b03e1..000000000 --- a/features/add-bond/add-bond-form/context/use-form-revalidate.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { UseFormReturn } from 'react-hook-form'; -import { AddBondFormInputType } from './types'; -import { useEffect } from 'react'; - -export const useFormRevalidate = ({ - watch, - trigger, -}: UseFormReturn) => { - const [token] = watch(['token']); - - useEffect(() => { - void trigger('bondAmount'); - }, [token, trigger]); -}; diff --git a/features/add-bond/add-bond-form/context/use-get-default-values.ts b/features/add-bond/add-bond-form/context/use-get-default-values.ts deleted file mode 100644 index b6db8b2c6..000000000 --- a/features/add-bond/add-bond-form/context/use-get-default-values.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { useMemo } from 'react'; -import { useDefaultValues } from 'shared/hooks'; -import { getMaxBalanceToken } from 'utils'; -import { AddBondFormInputType, AddBondFormNetworkData } from './types'; - -export const useGetDefaultValues = ({ - etherBalance, - stethBalance, - wstethBalance, - loading: { - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - }, -}: AddBondFormNetworkData) => { - return useDefaultValues( - useMemo(() => { - if ( - [ - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - ].some(Boolean) - ) { - return undefined; - } - - const token = getMaxBalanceToken({ - etherBalance, - stethBalance, - wstethBalance, - }); - - return { - token, - }; - }, [ - etherBalance, - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - stethBalance, - wstethBalance, - ]), - ); -}; diff --git a/features/add-bond/add-bond-form/controls/amount-input.tsx b/features/add-bond/add-bond-form/controls/amount-input.tsx index 4836d4458..fc31fb82e 100644 --- a/features/add-bond/add-bond-form/controls/amount-input.tsx +++ b/features/add-bond/add-bond-form/controls/amount-input.tsx @@ -8,7 +8,6 @@ export const AmountInput: React.FC = () => { const token = useWatch({ name: 'token' }); const max = useMaxValue(token); - // TODO: reset amount on token switch return ( <> Enter token amount diff --git a/features/add-bond/add-bond-form/controls/info.tsx b/features/add-bond/add-bond-form/controls/info.tsx index 54bf12f1c..0b4571ca5 100644 --- a/features/add-bond/add-bond-form/controls/info.tsx +++ b/features/add-bond/add-bond-form/controls/info.tsx @@ -1,47 +1,58 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { UNBONDED_VALIDATORS_LINK } from 'consts/external-links'; import { BOND_EXCESS, BOND_INSUFFICIENT } from 'consts/text'; -import { TOKENS } from 'consts/tokens'; import { FC } from 'react'; import { Latice, MatomoLink, Stack, TitledAmount } from 'shared/components'; import { useAddBondFormData } from '../context'; export const Info: FC = () => { - const { bond, loading } = useAddBondFormData(); + const { bond } = useAddBondFormData(true); return ( <> - + + {bond?.isInsufficient ? BOND_INSUFFICIENT : BOND_EXCESS} + + } help={ bond?.isInsufficient - ? 'Insufficient bond is the missing amount of stETH required to cover all operator’s keys. In case of a bond insufficient, "unbonded" validators are requested for exit by the protocol' - : 'The bond amount available to claim without having to exit validators' + ? 'Insufficient bond is the missing amount of stETH required to cover all operator’s keys. In case of a bond insufficient, "unbonded" validators are requested for exit by the protocol.' + : undefined } - loading={loading.isBondLoading} amount={bond?.delta} - token={TOKENS.STETH} + token={TOKENS.steth} + data-testid="titledAmount" /> {bond?.isInsufficient ? ( -

+

Your Node Operator has an Insufficient bond because of the penalty - applied. Now your Node Operator’s bond is less than required to - cover the Node Operator’s current validators. + applied. Now your Node Operator's bond is less than required + to cover the Node Operator's current validators.
Action required:
Top up the bond by submitting the required difference to be able to claim new rewards and to prevent your validator becoming - unbonded and being requested to exit. + unbonded and being requested to exit

) : ( -

+

Why you might need to add bond:
Adding a bond serves as a voluntary security measure for your Node Operator to prevent your validators from becoming{' '} - + unbonded {' '} and being requested to exit in case of applied penalties. diff --git a/features/add-bond/add-bond-form/controls/submit-button.tsx b/features/add-bond/add-bond-form/controls/submit-button.tsx index bcd979dd2..78b22233a 100644 --- a/features/add-bond/add-bond-form/controls/submit-button.tsx +++ b/features/add-bond/add-bond-form/controls/submit-button.tsx @@ -1,15 +1,12 @@ import { PausedButton, SubmitButtonHookForm } from 'shared/hook-form/controls'; -import { useAddBondFormData } from '../context'; +import { useAddBondFlow } from '../context'; export const SubmitButton = () => { - const { isPaused } = useAddBondFormData(); - if (isPaused) { + const flow = useAddBondFlow(); + + if (flow.action === 'paused') { return ; } - return ( - - Add Bond - - ); + return Add Bond; }; diff --git a/features/add-bond/add-bond-form/controls/token-select.tsx b/features/add-bond/add-bond-form/controls/token-select.tsx index 2f8813d73..1cba4c76a 100644 --- a/features/add-bond/add-bond-form/controls/token-select.tsx +++ b/features/add-bond/add-bond-form/controls/token-select.tsx @@ -1,37 +1,22 @@ -import { TOKENS } from 'consts/tokens'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; import { FormTitle, TokenAmount } from 'shared/components'; import { TokenButtonsHookForm } from 'shared/hook-form/controls'; import { useAddBondFormData } from '../context'; export const TokenSelect: React.FC = () => { - const { etherBalance, stethBalance, wstethBalance, loading } = - useAddBondFormData(); + const { ethBalance, stethBalance, wstethBalance } = useAddBondFormData(true); return ( <> Choose bond token + [TOKENS.eth]: , + [TOKENS.steth]: ( + ), - [TOKENS.STETH]: ( - - ), - [TOKENS.WSTETH]: ( - + [TOKENS.wsteth]: ( + ), }} /> diff --git a/features/add-bond/add-bond-form/hooks/use-max-value.ts b/features/add-bond/add-bond-form/hooks/use-max-value.ts index c261b81b9..09af64893 100644 --- a/features/add-bond/add-bond-form/hooks/use-max-value.ts +++ b/features/add-bond/add-bond-form/hooks/use-max-value.ts @@ -1,21 +1,20 @@ -import { Zero } from '@ethersproject/constants'; -import { TOKENS } from 'consts/tokens'; import { useMemo } from 'react'; import { useAddBondFormData } from '../context'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; export const useMaxValue = (token: TOKENS) => { - const { etherBalance, stethBalance, wstethBalance } = useAddBondFormData(); + const { ethBalance, stethBalance, wstethBalance } = useAddBondFormData(); const max = useMemo(() => { switch (token) { - case TOKENS.ETH: - return etherBalance; // TODO: minus gas cost - case TOKENS.STETH: + case TOKENS.eth: + return ethBalance; // TODO: minus gas cost + case TOKENS.steth: return stethBalance; - case TOKENS.WSTETH: + case TOKENS.wsteth: return wstethBalance; } - }, [etherBalance, stethBalance, token, wstethBalance]); + }, [ethBalance, stethBalance, token, wstethBalance]); - return max ?? Zero; + return max ?? 0n; }; diff --git a/features/add-bond/add-bond-form/hooks/use-receive-amount.ts b/features/add-bond/add-bond-form/hooks/use-receive-amount.ts deleted file mode 100644 index 681d143fc..000000000 --- a/features/add-bond/add-bond-form/hooks/use-receive-amount.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Zero } from '@ethersproject/constants'; -import { TOKENS } from 'consts/tokens'; -import { BigNumber } from 'ethers'; -import { useStethByWsteth } from 'shared/hooks'; - -export const useReceiveAmount = ( - amount: BigNumber | undefined, - token: TOKENS, -) => { - const { data: wsteth, loading: wstethLoadng } = useStethByWsteth( - (token === TOKENS.WSTETH && amount) || undefined, - ); - - return { - amount: (token === TOKENS.WSTETH ? wsteth : amount) ?? Zero, - loading: token === TOKENS.WSTETH ? wstethLoadng : false, - }; -}; diff --git a/features/add-bond/add-bond-form/hooks/use-tx-modal-stages-add-bond.tsx b/features/add-bond/add-bond-form/hooks/use-tx-modal-stages-add-bond.tsx index af60bc262..78eacf9ff 100644 --- a/features/add-bond/add-bond-form/hooks/use-tx-modal-stages-add-bond.tsx +++ b/features/add-bond/add-bond-form/hooks/use-tx-modal-stages-add-bond.tsx @@ -1,62 +1,44 @@ -import type { BigNumber } from 'ethers'; - -import { TOKENS } from 'consts/tokens'; +import { type AddBondResult, TOKENS } from '@lidofinance/lido-csm-sdk'; import { - TransactionModalTransitStage, TxStageOperationSucceedBalanceShown, TxStageSignOperationAmount, - getGeneralTransactionModalStages, - useTransactionModalStage, + useTxStages, } from 'shared/transaction-modal'; +import { AddBondFormInputType, AddBondFormNetworkData } from '../context/types'; const STAGE_OPERATION_ARGS = { operationText: 'Adding Bond', }; -type Props = { - amount: BigNumber; - token: TOKENS; -}; - -const getTxModalStagesAddBond = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: ({ amount, token }: Props) => - transitStage( - , - ), - - pending: ({ amount, token }: Props, txHash?: string) => - transitStage( - , - ), - - success: ({ balance }: { balance: BigNumber }, txHash?: string) => - transitStage( - , - { - isClosableOnLedger: true, - }, - ), -}); - -export const useTxModalStagesAddBond = () => { - return useTransactionModalStage(getTxModalStagesAddBond); -}; +export const useTxModalStagesAddBond = () => + useTxStages( + (transitStage, input) => ({ + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (result: AddBondResult, txHash) => + transitStage( + , + ), + }), + ); diff --git a/features/add-bond/add-bond-page.tsx b/features/add-bond/add-bond-page.tsx index e9865fc24..da82fdc59 100644 --- a/features/add-bond/add-bond-page.tsx +++ b/features/add-bond/add-bond-page.tsx @@ -3,15 +3,17 @@ import { FC } from 'react'; import { Layout } from 'shared/layout'; import { BondPageSwitcher } from 'shared/navigate'; import { AddBond } from './add-bond'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { Faq } from 'shared/components'; +import { FAQ_BOND } from 'faq'; export const AddBondPage: FC = () => ( + ); diff --git a/features/add-bond/add-bond.tsx b/features/add-bond/add-bond.tsx index b4f019d27..f7bd40d51 100644 --- a/features/add-bond/add-bond.tsx +++ b/features/add-bond/add-bond.tsx @@ -1,8 +1,7 @@ import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; +import { useWeb3Key } from 'shared/hooks'; import { AddBondForm } from './add-bond-form'; -import { Faq } from 'shared/components'; export const AddBond = () => { const key = useWeb3Key(); @@ -11,7 +10,6 @@ export const AddBond = () => { - ); }; diff --git a/features/add-keys/add-keys-page.tsx b/features/add-keys/add-keys-page.tsx index d98f57940..b169b4a46 100644 --- a/features/add-keys/add-keys-page.tsx +++ b/features/add-keys/add-keys-page.tsx @@ -3,15 +3,29 @@ import { FC } from 'react'; import { Layout } from 'shared/layout'; import { KeysPageSwitcher } from 'shared/navigate'; import { AddKeys } from './add-keys'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { Faq } from 'shared/components'; +import { FAQ_KEYS } from 'faq'; +import { useNodeOperatorId, useOperatorInfo } from 'modules/web3'; export const AddKeysPage: FC = () => ( } + pageName="AddKeys" > + ); + +const Subtitle: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: info } = useOperatorInfo(nodeOperatorId); + + if (info?.totalAddedKeys === 0) { + return <>Upload new keys; + } + + return <>Upload more keys; +}; diff --git a/features/add-keys/add-keys.tsx b/features/add-keys/add-keys.tsx index 8e11f466d..863edc480 100644 --- a/features/add-keys/add-keys.tsx +++ b/features/add-keys/add-keys.tsx @@ -1,8 +1,7 @@ import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; -import { AddKeysForm } from './add-keys/add-keys-form'; -import { Faq } from 'shared/components'; +import { useWeb3Key } from 'shared/hooks'; import { ShareLimitBanner } from '../create-node-operator/share-limit-banner'; +import { AddKeysForm } from './add-keys/add-keys-form'; export const AddKeys = () => { const key = useWeb3Key(); @@ -12,7 +11,6 @@ export const AddKeys = () => { - ); }; diff --git a/features/add-keys/add-keys/add-keys-form-info.tsx b/features/add-keys/add-keys/add-keys-form-info.tsx index d405a26a8..ee2cf98eb 100644 --- a/features/add-keys/add-keys/add-keys-form-info.tsx +++ b/features/add-keys/add-keys/add-keys-form-info.tsx @@ -1,25 +1,32 @@ import { DataTable, DataTableRow, Divider } from '@lidofinance/lido-ui'; import { useWatch } from 'react-hook-form'; import { AddKeysFormInputType, useAddKeysFormData } from './context'; +import { isModuleCM } from 'consts'; export const AddKeysFormInfo = () => { const [depositData] = useWatch({ name: ['depositData'], }); - const { shareLimit } = useAddKeysFormData(); + const { shareLimit } = useAddKeysFormData(true); return ( - {depositData.length} - - - {shareLimit?.queue.toString()} - + {!isModuleCM && ( + <> + + {depositData.length} + + + + + {shareLimit?.queue.toString()} + + + )} ); }; diff --git a/features/add-keys/add-keys/add-keys-form-loader.tsx b/features/add-keys/add-keys/add-keys-form-loader.tsx new file mode 100644 index 000000000..d2f47df70 --- /dev/null +++ b/features/add-keys/add-keys/add-keys-form-loader.tsx @@ -0,0 +1,20 @@ +import { FC, PropsWithChildren } from 'react'; +import { NoAccessNotice } from 'shared/components'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useAddKeysFlow } from './context'; + +const AddKeysFormGate: FC = ({ children }) => { + const flow = useAddKeysFlow(); + + if (flow.action === 'no-access') { + return ; + } + + return <>{children}; +}; + +export const AddKeysFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/add-keys/add-keys/add-keys-form.tsx b/features/add-keys/add-keys/add-keys-form.tsx index b4fbf5348..e4884d8be 100644 --- a/features/add-keys/add-keys/add-keys-form.tsx +++ b/features/add-keys/add-keys/add-keys-form.tsx @@ -1,36 +1,41 @@ import { FC, memo } from 'react'; -import { AddKeysFormProvider } from './context'; +import { AddKeysDataProvider, AddKeysFormProvider } from './context'; +import { DepositQueue } from 'features/view-keys/deposit-queue'; import { FormBlock } from 'shared/components'; -import { - BaseFormLoader, - FormControllerStyled, -} from 'shared/hook-form/form-controller'; +import { Form } from 'shared/hook-form/form-controller'; +import { Gate } from 'shared/navigate'; import { AddKeysFormInfo } from './add-keys-form-info'; +import { AddKeysFormLoader } from './add-keys-form-loader'; import { AmountInput } from './controls/amount-input'; +import { KeysConfirm } from './controls/keys-confirm'; import { KeysInput } from './controls/keys-input'; +import { KeysLimitWarning } from './controls/keys-limit-warning'; import { SubmitButton } from './controls/submit-button'; import { TokenSelect } from './controls/token-select'; -import { KeysConfirm } from './controls/keys-confirm'; -import { DepositQueue } from 'features/view-keys/deposit-queue'; export const AddKeysForm: FC = memo(() => { return ( - - - - - - - - - - - - - - - + + + + +

+ + + + + + + + + + + + + + + ); }); diff --git a/features/add-keys/add-keys/context/add-keys-data-provider.tsx b/features/add-keys/add-keys/context/add-keys-data-provider.tsx new file mode 100644 index 000000000..0e65b9bd5 --- /dev/null +++ b/features/add-keys/add-keys/context/add-keys-data-provider.tsx @@ -0,0 +1,139 @@ +import { + KEY_DEPOSIT_QUEUE_BATCHES, + KEY_OPERATOR_BALANCE, + KEY_OPERATOR_INFO, + KEY_OPERATOR_KEYS, + KEY_SHARE_LIMIT, + KEY_STAKE_LIMIT, + useSmStatus, + useCurveParameters, + useEthereumBalance, + useNodeOperatorId, + useOperatorBalance, + useOperatorCurveId, + useOperatorInfo, + useShareLimit, + useStakeLimit, + useStethBalance, + useWstethBalance, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate, useKeysAvailable } from 'shared/hooks'; +import { isModuleCSM } from 'consts'; +import { type AddKeysFormNetworkData } from './types'; + +const useAddKeysFormNetworkData: NetworkData = () => { + const { data: status, isPending: isStatusLoading } = useSmStatus(); + const nodeOperatorId = useNodeOperatorId(); + + const ethBalanceQuery = useEthereumBalance(); + const stethBalanceQuery = useStethBalance(); + const wstethBalanceQuery = useWstethBalance(); + const bondQuery = useOperatorBalance(nodeOperatorId); + const maxStakeEthQuery = useStakeLimit(); + const shareLimitQuery = useShareLimit(); + + const ethBalance = ethBalanceQuery.data; + const stethBalance = stethBalanceQuery.data; + const wstethBalance = wstethBalanceQuery.data; + const bond = bondQuery.data; + const maxStakeEth = maxStakeEthQuery.data; + const shareLimit = shareLimitQuery.data; + + const isEthBalanceLoading = ethBalanceQuery.isPending; + const isStethBalanceLoading = stethBalanceQuery.isPending; + const isWstethBalanceLoading = wstethBalanceQuery.isPending; + const isBondLoading = bondQuery.isPending; + const isMaxStakeEthLoading = maxStakeEthQuery.isPending; + const isShareLimitLoading = shareLimitQuery.isPending; + + const { data: curveId, isPending: isCurveIdLoading } = + useOperatorCurveId(nodeOperatorId); + const { data: curveParameters, isPending: isCurveParametersLoading } = + useCurveParameters(curveId); + + const { data: operatorInfo, isPending: isOperatorInfoLoading } = + useOperatorInfo(nodeOperatorId); + + const nonWithdrawnKeys = operatorInfo + ? operatorInfo.totalAddedKeys - operatorInfo.totalWithdrawnKeys + : undefined; + + const keysAvailable = useKeysAvailable({ + curveId, + nonWithdrawnKeys, + bond, + ethBalance, + stethBalance, + wstethBalance, + }); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ + ethBalanceQuery.queryKey, + stethBalanceQuery.queryKey, + wstethBalanceQuery.queryKey, + KEY_OPERATOR_BALANCE, + KEY_SHARE_LIMIT, + KEY_STAKE_LIMIT, + KEY_OPERATOR_INFO, + KEY_OPERATOR_KEYS, + KEY_DEPOSIT_QUEUE_BATCHES, + ]); + }, [ + invalidate, + ethBalanceQuery.queryKey, + stethBalanceQuery.queryKey, + wstethBalanceQuery.queryKey, + ]); + + const isPending = + isEthBalanceLoading || + isStethBalanceLoading || + isWstethBalanceLoading || + isMaxStakeEthLoading || + isCurveParametersLoading || + isBondLoading || + isStatusLoading || + (isModuleCSM && isShareLimitLoading) || + isCurveIdLoading || + isOperatorInfoLoading; + + return { + data: { + nodeOperatorId, + curveId, + operatorInfo, + curveParameters, + stethBalance, + wstethBalance, + ethBalance, + bond, + maxStakeEth, + shareLimit, + isPaused: status?.isPaused, + keysAvailable, + } as AddKeysFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useAddKeysFormData = useFormData; + +export const AddKeysDataProvider: FC = ({ children }) => { + const networkData = useAddKeysFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/add-keys/add-keys/context/add-keys-form-provider.tsx b/features/add-keys/add-keys/context/add-keys-form-provider.tsx index 33b13e32a..2230136c5 100644 --- a/features/add-keys/add-keys/context/add-keys-form-provider.tsx +++ b/features/add-keys/add-keys/context/add-keys-form-provider.tsx @@ -1,62 +1,33 @@ -import { FC, PropsWithChildren, useMemo } from 'react'; +import { FC, PropsWithChildren } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormData, - useFormDepositData, + FormControllerProvider, + useFlowSubmit, } from 'shared/hook-form/form-controller'; -import { useFormControllerRetry } from 'shared/hook-form/form-controller/use-form-controller-retry-delegate'; -import { AddKeysFormInputType, AddKeysFormNetworkData } from './types'; -import { useAddKeysFormNetworkData } from './use-add-keys-form-network-data'; -import { useAddKeysSubmit } from './use-add-keys-submit'; +import { AddKeysUpdater } from './add-keys-updater'; +import { AddKeysFormInputType } from './types'; +import { useAddKeysFlowResolver } from './use-add-keys-flow'; +import { useAddKeysDefaultValues } from './use-add-keys-default-values'; import { useAddKeysValidation } from './use-add-keys-validation'; -import { useFormBondAmount } from './use-form-bond-amount'; -import { useGetDefaultValues } from './use-get-default-values'; - -export const useAddKeysFormData = useFormData; export const AddKeysFormProvider: FC = ({ children }) => { - const [networkData, revalidate] = useAddKeysFormNetworkData(); - const validationResolver = useAddKeysValidation(networkData); - - const asyncDefaultValues = useGetDefaultValues(networkData); + const resolver = useAddKeysValidation(); + const asyncDefaultValues = useAddKeysDefaultValues(); const formObject = useForm({ defaultValues: asyncDefaultValues, - resolver: validationResolver, + resolver, mode: 'onChange', }); - useFormBondAmount(formObject, networkData); - useFormDepositData(formObject); - - const { retryEvent, retryFire } = useFormControllerRetry(); - - const addKeys = useAddKeysSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - AddKeysFormInputType, - AddKeysFormNetworkData - > = useMemo( - () => ({ - onSubmit: addKeys, - retryEvent, - }), - [addKeys, retryEvent], - ); + const submitter = useFlowSubmit(useAddKeysFlowResolver()); return ( - - - {children} - - + + + {children} + ); }; diff --git a/features/add-keys/add-keys/context/add-keys-updater.tsx b/features/add-keys/add-keys/context/add-keys-updater.tsx new file mode 100644 index 000000000..3637aa349 --- /dev/null +++ b/features/add-keys/add-keys/context/add-keys-updater.tsx @@ -0,0 +1,38 @@ +import { useBondNextKeysCount } from 'modules/web3'; +import { FC, useEffect } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { useAddKeysFormData } from './add-keys-data-provider'; +import { AddKeysFormInputType } from './types'; + +export const AddKeysUpdater: FC = () => { + const [token, depositData] = useWatch< + AddKeysFormInputType, + ['token', 'depositData'] + >({ name: ['token', 'depositData'] }); + + const keysCount = depositData?.length ?? 0; + + const { trigger, setValue } = useFormContext(); + + const { nodeOperatorId } = useAddKeysFormData(); + + const { data: bondAmount } = useBondNextKeysCount({ + nodeOperatorId, + keysCount, + token, + }); + + useEffect(() => { + void trigger('bondAmount'); + // trigger is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [token]); + + useEffect(() => { + setValue('bondAmount', bondAmount, { shouldValidate: true }); + // setValue is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [bondAmount]); + + return null; +}; diff --git a/features/add-keys/add-keys/context/index.ts b/features/add-keys/add-keys/context/index.ts index d344aeb8e..ea92e7d00 100644 --- a/features/add-keys/add-keys/context/index.ts +++ b/features/add-keys/add-keys/context/index.ts @@ -1,2 +1,4 @@ export * from './add-keys-form-provider'; +export * from './add-keys-data-provider'; export * from './types'; +export * from './use-add-keys-flow'; diff --git a/features/add-keys/add-keys/context/types.ts b/features/add-keys/add-keys/context/types.ts index d0feb4729..6b13a1663 100644 --- a/features/add-keys/add-keys/context/types.ts +++ b/features/add-keys/add-keys/context/types.ts @@ -1,35 +1,30 @@ -import { type TOKENS } from 'consts/tokens'; -import { BigNumber } from 'ethers'; -import { DepositDataInputType } from 'shared/hook-form/form-controller'; -import { KeysAvailable, ShareLimitInfo } from 'shared/hooks'; -import { BondBalance, LoadingRecord, NodeOperatorId } from 'types'; +import { + BondBalance, + CurveParameters, + NodeOperatorId, + NodeOperatorInfo, + ShareLimitInfo, + TOKENS, +} from '@lidofinance/lido-csm-sdk'; +import { DepositDataInputType } from 'shared/hook-form/deposit-data'; +import { KeysAvailable } from 'shared/hooks'; export type AddKeysFormInputType = { token: TOKENS; - bondAmount?: BigNumber; + bondAmount?: bigint; } & DepositDataInputType; export type AddKeysFormNetworkData = { - etherBalance?: BigNumber; - stethBalance?: BigNumber; - wstethBalance?: BigNumber; - nodeOperatorId?: NodeOperatorId; - keysUploadLimit?: number; - keysAvailable?: KeysAvailable; - bond?: BondBalance; - isPaused?: boolean; - maxStakeEther?: BigNumber | null; + ethBalance: bigint; + stethBalance: bigint; + wstethBalance: bigint; + nodeOperatorId: NodeOperatorId; + curveId: bigint; + operatorInfo: NodeOperatorInfo; + curveParameters: CurveParameters; + bond: BondBalance; + isPaused: boolean; + maxStakeEth: bigint; shareLimit?: ShareLimitInfo; - blockNumber?: number; - loading: LoadingRecord< - | 'etherBalance' - | 'stethBalance' - | 'wstethBalance' - | 'bond' - | 'maxStakeEther' - | 'keysUploadLimit' - | 'status' - | 'shareLimit' - | 'blockNumber' - >; + keysAvailable?: KeysAvailable; }; diff --git a/features/add-keys/add-keys/context/use-add-keys-default-values.ts b/features/add-keys/add-keys/context/use-add-keys-default-values.ts new file mode 100644 index 000000000..bfd10ef2f --- /dev/null +++ b/features/add-keys/add-keys/context/use-add-keys-default-values.ts @@ -0,0 +1,19 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { getMaxBalanceToken } from 'modules/web3'; +import { useFormDefaultValues } from 'shared/hook-form/form-controller'; +import { AddKeysFormInputType, AddKeysFormNetworkData } from './types'; + +export const useAddKeysDefaultValues = () => { + return useFormDefaultValues( + (data) => ({ + token: getMaxBalanceToken({ + [TOKENS.eth]: data.ethBalance, + [TOKENS.steth]: data.stethBalance, + [TOKENS.wsteth]: data.wstethBalance, + }), + depositData: [], + rawDepositData: '', + confirmKeysReady: false, + }), + ); +}; diff --git a/features/add-keys/add-keys/context/use-add-keys-flow.ts b/features/add-keys/add-keys/context/use-add-keys-flow.ts new file mode 100644 index 000000000..d07cbc387 --- /dev/null +++ b/features/add-keys/add-keys/context/use-add-keys-flow.ts @@ -0,0 +1,61 @@ +import { type MethodAccess } from '@lidofinance/lido-csm-sdk'; +import { PATH } from 'consts/urls'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useCanPerform } from 'shared/hooks'; +import { useNavigate } from 'shared/navigate'; +import invariant from 'tiny-invariant'; +import { useTxModalStagesAddKeys } from '../hooks/use-tx-modal-stages-add-keys'; +import { useAddKeysFormData } from './add-keys-data-provider'; +import { AddKeysFormInputType, AddKeysFormNetworkData } from './types'; + +export type AddKeysFlow = + | { action: 'no-access'; access: MethodAccess } + | ({ action: 'add-keys' } & Executable); + +export const useAddKeysFlowResolver = (): FlowResolver< + AddKeysFormInputType, + AddKeysFormNetworkData, + AddKeysFlow +> => { + const { keys: keysSDK } = useSmSDK(); + const [canAddKeys, addKeysAccess] = useCanPerform(keysSDK, 'addKeys'); + const n = useNavigate(); + const buildCallback = useTxModalStagesAddKeys(); + + return useCallback( + (input, data) => { + if (!canAddKeys) return { action: 'no-access', access: addKeysAccess }; + + const { depositData, token, bondAmount: amount } = input; + + return { + action: 'add-keys' as const, + submit: async () => { + invariant(amount !== undefined, 'BondAmount is not defined'); + + await keysSDK.addKeys({ + nodeOperatorId: data.nodeOperatorId, + token, + amount, + depositData, + callback: buildCallback(input, data), + }); + + void n(PATH.KEYS_VIEW); + }, + }; + }, + [keysSDK, canAddKeys, addKeysAccess, n, buildCallback], + ); +}; + +export const useAddKeysFlow = (): AddKeysFlow => { + const resolve = useAddKeysFlowResolver(); + const data = useAddKeysFormData(true); + return resolve({} as AddKeysFormInputType, data); +}; diff --git a/features/add-keys/add-keys/context/use-add-keys-form-network-data.tsx b/features/add-keys/add-keys/context/use-add-keys-form-network-data.tsx deleted file mode 100644 index 1bb8aeb25..000000000 --- a/features/add-keys/add-keys/context/use-add-keys-form-network-data.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { - useEthereumBalance, - useSTETHBalance, - useWSTETHBalance, -} from '@lido-sdk/react'; -import { STRATEGY_LAZY } from 'consts/swr-strategies'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { useCallback, useMemo } from 'react'; -import { - useCsmPaused, - useCSMShareLimitInfo, - useKeysAvailable, - useKeysUploadLimit, - useNodeOperatorBalance, - useNodeOperatorCurveId, - useNonWithdrawnKeysCount, - useStakingLimitInfo, -} from 'shared/hooks'; -import { useBlockNumber } from 'wagmi'; -import { type AddKeysFormNetworkData } from './types'; - -export const useAddKeysFormNetworkData = (): [ - AddKeysFormNetworkData, - () => Promise, -] => { - const { data: blockNumber, isLoading: isBlockNumberLoading } = - useBlockNumber(); - const { data: status, initialLoading: isStatusLoading } = useCsmPaused(); - const nodeOperatorId = useNodeOperatorId(); - const { - data: etherBalance, - update: updateEtherBalance, - initialLoading: isEtherBalanceLoading, - } = useEthereumBalance(undefined, STRATEGY_LAZY); - const { - data: stethBalance, - update: updateStethBalance, - initialLoading: isStethBalanceLoading, - } = useSTETHBalance(STRATEGY_LAZY); - const { - data: wstethBalance, - update: updateWstethBalance, - initialLoading: isWstethBalanceLoading, - } = useWSTETHBalance(STRATEGY_LAZY); - const { - data: bond, - update: updateBond, - initialLoading: isBondLoading, - } = useNodeOperatorBalance(nodeOperatorId); - const { - data: maxStakeEther, - update: updateMaxStakeEther, - initialLoading: isMaxStakeEtherLoading, - } = useStakingLimitInfo(); - - const { - data: shareLimit, - initialLoading: isShareLimitLoading, - update: updateShareLimit, - } = useCSMShareLimitInfo(); - - const { - data: keysUploadLimit, - update: updateKeysUploadLimit, - initialLoading: isKeysUploadLimitLoading, - } = useKeysUploadLimit(); - - const { data: curveId } = useNodeOperatorCurveId(nodeOperatorId); - - const { data: nonWithdrawnKeys } = useNonWithdrawnKeysCount(nodeOperatorId); - - const { data: keysAvailable } = useKeysAvailable({ - curveId, - keysUploadLimit, - nonWithdrawnKeys, - bond, - etherBalance, - stethBalance, - wstethBalance, - }); - - const revalidate = useCallback(async () => { - await Promise.allSettled([ - updateStethBalance(), - updateWstethBalance(), - updateEtherBalance(), - updateBond(), - updateKeysUploadLimit(), - updateShareLimit(), - updateMaxStakeEther(), - ]); - }, [ - updateStethBalance, - updateWstethBalance, - updateEtherBalance, - updateBond, - updateKeysUploadLimit, - updateShareLimit, - updateMaxStakeEther, - ]); - - const loading = useMemo( - () => ({ - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - isMaxStakeEtherLoading, - isBondLoading, - isKeysUploadLimitLoading, - isStatusLoading, - isBlockNumberLoading, - isShareLimitLoading, - }), - [ - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - isMaxStakeEtherLoading, - isBondLoading, - isKeysUploadLimitLoading, - isStatusLoading, - isBlockNumberLoading, - isShareLimitLoading, - ], - ); - - return [ - { - blockNumber, - nodeOperatorId, - keysUploadLimit, - keysAvailable, - stethBalance, - wstethBalance, - etherBalance, - bond, - maxStakeEther, - loading, - shareLimit, - isPaused: status?.isPaused || status?.isAccountingPaused, - }, - revalidate, - ]; -}; diff --git a/features/add-keys/add-keys/context/use-add-keys-submit.ts b/features/add-keys/add-keys/context/use-add-keys-submit.ts deleted file mode 100644 index 175ad2dc3..000000000 --- a/features/add-keys/add-keys/context/use-add-keys-submit.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { TOKENS } from 'consts/tokens'; -import { BigNumber } from 'ethers'; -import { BytesLike } from 'ethers/lib/utils.js'; -import { useCallback } from 'react'; -import { - GatherPermitSignatureResult, - useCSModuleWeb3, - useKeysCache, - usePermitOrApprove, - useSendTx, -} from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import invariant from 'tiny-invariant'; -import { NodeOperatorId } from 'types'; -import { addExtraWei, formatKeys, runWithTransactionLogger } from 'utils'; -import { useTxModalStagesAddKeys } from '../hooks/use-tx-modal-stages-add-keys'; -import { AddKeysFormInputType, AddKeysFormNetworkData } from './types'; - -type AddKeysOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type MethodParams = { - nodeOperatorId: NodeOperatorId; - bondAmount: BigNumber; - keysCount: number; - publicKeys: BytesLike; - signatures: BytesLike; - permit: GatherPermitSignatureResult; -}; - -// this encapsulates eth/steth/wsteth flows -const useAddKeysTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async (token: TOKENS, params: MethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - switch (true) { - case token === TOKENS.STETH || params.bondAmount.isZero(): - return { - tx: await CSModuleWeb3.populateTransaction.addValidatorKeysStETH( - params.nodeOperatorId, - params.keysCount, - params.publicKeys, - params.signatures, - params.permit, - ), - txName: 'addValidatorKeysStETH', - }; - case token === TOKENS.ETH: - return { - tx: await CSModuleWeb3.populateTransaction.addValidatorKeysETH( - params.nodeOperatorId, - params.keysCount, - params.publicKeys, - params.signatures, - { value: params.bondAmount }, - ), - txName: 'addValidatorKeysETH', - }; - case token === TOKENS.WSTETH: - return { - tx: await CSModuleWeb3.populateTransaction.addValidatorKeysWstETH( - params.nodeOperatorId, - params.keysCount, - params.publicKeys, - params.signatures, - params.permit, - ), - txName: 'addValidatorKeysWstETH', - }; - default: { - throw new Error('Not implemented yet: true case'); - } - } - }, - [CSModuleWeb3], - ); -}; - -export const useAddKeysSubmit = ({ onConfirm, onRetry }: AddKeysOptions) => { - const { txModalStages } = useTxModalStagesAddKeys(); - const getPermitOrApprove = usePermitOrApprove(); - const getTx = useAddKeysTx(); - const sendTx = useSendTx(); - - const { addCacheKeys } = useKeysCache(); - - return useCallback( - async ( - { depositData, token, bondAmount }: AddKeysFormInputType, - { nodeOperatorId }: AddKeysFormNetworkData, - ): Promise => { - invariant(nodeOperatorId, 'NodeOperatorId is not defined'); - invariant(depositData.length, 'Keys is not defined'); - invariant(token, 'Token is not defined'); - invariant(bondAmount, 'BondAmount is not defined'); - - try { - const { permit } = await getPermitOrApprove({ - token, - amount: addExtraWei(bondAmount, token), - txModalStages, - }); - - const { keysCount, publicKeys, signatures } = formatKeys(depositData); - - txModalStages.sign({ - keysCount, - amount: bondAmount, - token, - nodeOperatorId, - }); - - const tx = await getTx(token, { - nodeOperatorId, - bondAmount, - keysCount, - publicKeys, - signatures, - permit, - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'AddKeys signing', - () => sendTx(tx), - ); - - txModalStages.pending( - { keysCount, amount: bondAmount, token, nodeOperatorId }, - txHash, - ); - - await runWithTransactionLogger('AddKeys block confirmation', waitTx); - - await onConfirm?.(); - - txModalStages.success( - { keys: depositData.map((key) => key.pubkey) }, - txHash, - ); - - // TODO: move to onConfirm - void addCacheKeys(depositData.map(({ pubkey }) => pubkey)); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [ - getPermitOrApprove, - txModalStages, - getTx, - onConfirm, - addCacheKeys, - sendTx, - onRetry, - ], - ); -}; diff --git a/features/add-keys/add-keys/context/use-add-keys-validation.ts b/features/add-keys/add-keys/context/use-add-keys-validation.ts index ed7032c9b..68335e522 100644 --- a/features/add-keys/add-keys/context/use-add-keys-validation.ts +++ b/features/add-keys/add-keys/context/use-add-keys-validation.ts @@ -1,71 +1,80 @@ -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; +import { useFeatureFlags } from 'config/feature-flags'; +import { DISABLE_DEPOSIT_DATA_VALIDATION } from 'config/feature-flags/types'; +import { useSmSDK } from 'modules/web3'; import { - handleResolverValidationError, + useFormValidation, validateBondAmount, validateDepositData, ValidationError, } from 'shared/hook-form/validation'; -import { useAccount, useAwaitNetworkData } from 'shared/hooks'; import type { AddKeysFormInputType, AddKeysFormNetworkData } from './types'; -export const useAddKeysValidation = (networkData: AddKeysFormNetworkData) => { - const dataPromise = useAwaitNetworkData(networkData); - const { chainId } = useAccount(); +export const useAddKeysValidation = () => { + const { depositData: sdk } = useSmSDK(); + const featureFlags = useFeatureFlags(); - return useCallback>( - async (values, _, options) => { - try { - const { token, bondAmount, depositData, confirmKeysReady } = values; - - const { - stethBalance, - wstethBalance, - etherBalance, - maxStakeEther, - keysUploadLimit, - blockNumber, - } = await dataPromise; + return useFormValidation( + 'token', + async ( + { token, bondAmount, depositData, rawDepositData, confirmKeysReady }, + { + operatorInfo, + curveParameters, + maxStakeEth, + ethBalance, + stethBalance, + wstethBalance, + }, + validate, + ) => { + // FIXME: validate on submit that token, bondAmount and depositData.length are defined + await validate(['token', 'bondAmount'], () => validateBondAmount({ token, bondAmount, - maxStakeEther, - etherBalance, + maxStakeEth, + ethBalance, stethBalance, wstethBalance, - }); + }), + ); - if ( - options.names?.includes('depositData') || - options.names?.includes('rawDepositData') - ) + // TODO: validate length is zero + await validate('rawDepositData', () => { + if (rawDepositData) { + const { error } = sdk.parseDepositData(rawDepositData); + if (error) { + throw new ValidationError('rawDepositData', error); + } + } else { + throw new ValidationError('rawDepositData', ''); + } + }); + + // TODO: refactor this validation + await validate(['rawDepositData', 'depositData'], async () => { + if (!featureFlags?.[DISABLE_DEPOSIT_DATA_VALIDATION]) { await validateDepositData({ depositData, - chainId, - keysUploadLimit, - blockNumber, + sdk, + keysLimit: curveParameters?.keysLimit, + nonWithdrawnKeys: + operatorInfo && + operatorInfo.totalAddedKeys - operatorInfo.totalWithdrawnKeys, }); + } + }); - if (options.names?.includes('confirmKeysReady') && !confirmKeysReady) { + await validate('confirmKeysReady', () => { + if (!confirmKeysReady) { throw new ValidationError( 'confirmKeysReady', 'Please confirm that the keys are ready', ); } - - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError( - error, - 'AddKeysForm', - 'depositData', - ); - } + }); }, - [chainId, dataPromise], + [sdk], ); }; diff --git a/features/add-keys/add-keys/context/use-form-bond-amount.ts b/features/add-keys/add-keys/context/use-form-bond-amount.ts deleted file mode 100644 index 3661fd71c..000000000 --- a/features/add-keys/add-keys/context/use-form-bond-amount.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useEffect } from 'react'; -import { UseFormReturn } from 'react-hook-form'; -import { useNodeOperatorNextKeysBond } from 'shared/hooks'; -import { AddKeysFormInputType, AddKeysFormNetworkData } from './types'; - -export const useFormBondAmount = ( - { watch, setValue, trigger }: UseFormReturn, - { nodeOperatorId }: AddKeysFormNetworkData, -) => { - const [token, depositData] = watch(['token', 'depositData']); - - const { data: bondAmount } = useNodeOperatorNextKeysBond({ - nodeOperatorId, - keysCount: depositData?.length, - token, - }); - - // TODO: move to somethere - useEffect(() => { - void trigger('bondAmount'); - }, [token, trigger]); - - useEffect(() => { - setValue('bondAmount', bondAmount, { shouldValidate: true }); - }, [bondAmount, setValue]); -}; diff --git a/features/add-keys/add-keys/context/use-get-default-values.ts b/features/add-keys/add-keys/context/use-get-default-values.ts deleted file mode 100644 index 468d9bd75..000000000 --- a/features/add-keys/add-keys/context/use-get-default-values.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { useMemo } from 'react'; -import { useDefaultValues } from 'shared/hooks'; -import { getMaxBalanceToken } from 'utils'; -import { AddKeysFormInputType, AddKeysFormNetworkData } from './types'; - -export const useGetDefaultValues = ({ - etherBalance, - stethBalance, - wstethBalance, - loading: { - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - }, -}: AddKeysFormNetworkData) => { - return useDefaultValues( - useMemo(() => { - if ( - [ - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - ].some(Boolean) - ) { - return undefined; - } - - const token = getMaxBalanceToken({ - etherBalance, - stethBalance, - wstethBalance, - }); - - return { - token, - depositData: [], - rawDepositData: '', - confirmKeysReady: false, - }; - }, [ - etherBalance, - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - stethBalance, - wstethBalance, - ]), - ); -}; diff --git a/features/add-keys/add-keys/controls/amount-input.tsx b/features/add-keys/add-keys/controls/amount-input.tsx index d22fb8481..4fe30288a 100644 --- a/features/add-keys/add-keys/controls/amount-input.tsx +++ b/features/add-keys/add-keys/controls/amount-input.tsx @@ -1,7 +1,7 @@ import { useFormState, useWatch } from 'react-hook-form'; import { InputAmount } from 'shared/components/input-amount'; -import { getTokenDisplayName } from 'utils/getTokenDisplayName'; +import { getTokenDisplayName } from 'utils'; import { AddKeysFormInputType } from '../context'; export const AmountInput = () => { @@ -13,11 +13,12 @@ export const AmountInput = () => { return ( ); }; diff --git a/features/add-keys/add-keys/controls/keys-confirm.tsx b/features/add-keys/add-keys/controls/keys-confirm.tsx index d604a0738..dcacd2d9c 100644 --- a/features/add-keys/add-keys/controls/keys-confirm.tsx +++ b/features/add-keys/add-keys/controls/keys-confirm.tsx @@ -1,41 +1,54 @@ import { Text } from '@lidofinance/lido-ui'; +import { isModuleCM } from 'consts'; +import { SHARE_LIMIT_STATUS, useShareLimitStatus } from 'modules/web3'; import { FC } from 'react'; import { Stack } from 'shared/components'; import { CheckboxHookForm } from 'shared/hook-form/controls'; -import { SHARE_LIMIT_STATUS } from 'shared/hooks'; -import { useAddKeysFormData } from '../context'; +import { useDepositDataValid } from 'shared/hook-form/deposit-data'; export const KeysConfirm: FC = () => { - const { shareLimit } = useAddKeysFormData(); + const { data: status } = useShareLimitStatus(); + const isDepositDataValid = useDepositDataValid(); return ( - - - - I confirm that: -
    -
  • - My nodes are synced, running, and ready for the validator activation -
  • - {shareLimit?.status === SHARE_LIMIT_STATUS.APPROACHING && ( + + + {isModuleCM ? ( + + I confirm that my nodes are synced, running, and ready for the + validator activation + + ) : ( + + I confirm that: +
    • - I understand that the deposit time for my keys can be months or - longer because CSM is approaching its stake share limit + My nodes are synced, running, and ready for the validator + activation
    • - )} - {shareLimit?.status === SHARE_LIMIT_STATUS.REACHED && ( + {status === SHARE_LIMIT_STATUS.APPROACHING && ( +
    • + I understand that the deposit time for my keys can be months or + longer because CSM is approaching its stake share limit +
    • + )} + {status === SHARE_LIMIT_STATUS.REACHED && ( +
    • + I understand that my newly uploaded keys are very unlikely to + receive deposits in the near future because CSM has reached its + stake share limit +
    • + )}
    • - I understand that my newly uploaded keys are very unlikely to - receive deposits in the near future because CSM has reached its - stake share limit + I understand that deleting keys from the deposit queue will incur + a removal fee
    • - )} -
    • - I understand that deleting keys from the deposit queue will incur a - removal fee -
    • -
    -
    +
+
+ )}
); }; diff --git a/features/add-keys/add-keys/controls/keys-input.tsx b/features/add-keys/add-keys/controls/keys-input.tsx index 91332778a..4d25ac57e 100644 --- a/features/add-keys/add-keys/controls/keys-input.tsx +++ b/features/add-keys/add-keys/controls/keys-input.tsx @@ -1,31 +1,28 @@ -import { ABOUT_DEPOSIT_DATA_LINK } from 'consts/external-links'; +import { isModuleCM } from 'consts'; +import { UPLOAD_DEPOSIT_DATA_LINK } from 'consts/external-links'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { useFormState } from 'react-hook-form'; import { FormTitle, MatomoLink } from 'shared/components'; -import { DepositDataInputHookForm } from 'shared/hook-form/controls'; -import { AddKeysFormInputType } from '../context'; +import { DepositDataHookForm } from 'shared/hook-form/controls'; export const KeysInput = () => { - const { errors } = useFormState({ - name: ['depositData', 'rawDepositData'], - }); - const error = errors.rawDepositData?.message || errors.depositData?.message; - return ( <> - Learn more - + isModuleCM ? null : ( + + Learn more + + ) } > Upload deposit data - + + ); }; diff --git a/features/add-keys/add-keys/controls/keys-limit-warning.tsx b/features/add-keys/add-keys/controls/keys-limit-warning.tsx new file mode 100644 index 000000000..83614541d --- /dev/null +++ b/features/add-keys/add-keys/controls/keys-limit-warning.tsx @@ -0,0 +1,18 @@ +import { FC } from 'react'; +import { KeysLimitWarning as KeysLimitWarningBlock } from 'shared/components'; +import { useAddKeysFormData } from '../context'; + +export const KeysLimitWarning: FC = () => { + const { curveParameters, operatorInfo } = useAddKeysFormData(); + + return ( + + ); +}; diff --git a/features/add-keys/add-keys/controls/submit-button.tsx b/features/add-keys/add-keys/controls/submit-button.tsx index fb7231909..68d882950 100644 --- a/features/add-keys/add-keys/controls/submit-button.tsx +++ b/features/add-keys/add-keys/controls/submit-button.tsx @@ -1,32 +1,22 @@ -import { Note } from 'shared/components'; +import { useWatch } from 'react-hook-form'; import { PausedButton, SubmitButtonHookForm } from 'shared/hook-form/controls'; -import { useKeysTotalLimit } from 'shared/hooks'; -import { useAddKeysFormData } from '../context'; +import { AddKeysFormInputType, useAddKeysFormData } from '../context'; export const SubmitButton = () => { - const { keysUploadLimit, isPaused } = useAddKeysFormData(); - const { data: keysTotalLimit } = useKeysTotalLimit(); - - const keysLimitReached = keysUploadLimit === 0; + const { isPaused } = useAddKeysFormData(); + const depositData = useWatch({ + name: 'depositData', + }); if (isPaused) { return ; } + const disabled = !depositData?.length; + return ( - <> - - {keysLimitReached ? 'Keys limit has been reached' : 'Submit keys'} - - {keysLimitReached && keysTotalLimit && ( - - You have reached the Early Access upload limit of {keysTotalLimit}{' '} - keys. You cannot upload more. - - )} - + + {'Submit keys'} + ); }; diff --git a/features/add-keys/add-keys/controls/token-select.tsx b/features/add-keys/add-keys/controls/token-select.tsx index 55c57edc6..eb733c3df 100644 --- a/features/add-keys/add-keys/controls/token-select.tsx +++ b/features/add-keys/add-keys/controls/token-select.tsx @@ -1,10 +1,13 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { isModuleCM } from 'consts'; +import { CM_BOND_AMOUNTS_LINK } from 'consts/external-links'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; import { BOND_EXCESS, BOND_INSUFFICIENT } from 'consts/text'; -import { TOKENS } from 'consts/tokens'; import { PATH } from 'consts/urls'; import { FormTitle, KeysAvailable, + MatomoLink, Stack, TitledAmount, TokenAmount, @@ -14,75 +17,76 @@ import { LocalLink } from 'shared/navigate'; import { useAddKeysFormData } from '../context'; export const TokenSelect: React.FC = () => { - const { - etherBalance, - stethBalance, - wstethBalance, - keysAvailable, - bond, - loading, - } = useAddKeysFormData(); + const { ethBalance, stethBalance, wstethBalance, keysAvailable, bond } = + useAddKeysFormData(true); return ( <> - How bond is calculated - + isModuleCM ? ( + + How bond is calculated + + ) : ( + + How bond is calculated + + ) } > Choose bond token - + -
), - [TOKENS.STETH]: ( + [TOKENS.steth]: ( - + - ), - [TOKENS.WSTETH]: ( + [TOKENS.wsteth]: ( - + - ), }} /> - + {bond.delta && ( + + )} ); }; diff --git a/features/add-keys/add-keys/hooks/use-tx-modal-stages-add-keys.tsx b/features/add-keys/add-keys/hooks/use-tx-modal-stages-add-keys.tsx index a084dd0a9..e0d7728f5 100644 --- a/features/add-keys/add-keys/hooks/use-tx-modal-stages-add-keys.tsx +++ b/features/add-keys/add-keys/hooks/use-tx-modal-stages-add-keys.tsx @@ -1,79 +1,56 @@ -import { TOKENS } from 'consts/tokens'; -import type { BigNumber } from 'ethers'; import { AfterKeysUpload, - TransactionModalTransitStage, TxStageSuccess, - getGeneralTransactionModalStages, - useTransactionModalStage, + useTxStages, } from 'shared/transaction-modal'; import { TxStageSignOperationKeys } from 'shared/transaction-modal/tx-stages-composed/tx-stage-keys-operation'; -import { NodeOperatorId } from 'types'; +import { AddKeysFormInputType, AddKeysFormNetworkData } from '../context/types'; const STAGE_OPERATION_ARGS = { operationText: 'Uploading', }; -type Props = { - keysCount: number; - amount: BigNumber; - token: TOKENS; - nodeOperatorId: NodeOperatorId; -}; - -type SuccessProps = { - keys: string[]; -}; - -const getTxModalStagesAddKeys = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: (props: Props) => - transitStage( - , - ), - - pending: (props: Props, txHash?: string) => - transitStage( - , - ), - - success: ({ keys }: SuccessProps, txHash?: string) => - transitStage( - Your keys has been uploaded} - description={ - <> - Uploading operation was successful. -
-
- - - } - />, - { - isClosableOnLedger: true, - }, - ), -}); - -export const useTxModalStagesAddKeys = () => { - return useTransactionModalStage(getTxModalStagesAddKeys); -}; +export const useTxModalStagesAddKeys = () => + useTxStages( + (transitStage, input, data) => ({ + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (_result, txHash) => + transitStage( + Your keys have been uploaded} + description={ + <> + Uploading operation was successful. +
+
+ key.pubkey)} + /> + + } + />, + ), + }), + ); diff --git a/features/change-role/change-manager-role-page.tsx b/features/change-role/change-manager-role-page.tsx deleted file mode 100644 index 9b427ede5..000000000 --- a/features/change-role/change-manager-role-page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { FC } from 'react'; - -import { Layout } from 'shared/layout'; -import { RolesPageSwitcher } from 'shared/navigate'; -import { ChangeManagerRole } from './change-manager-role'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; - -export const ChangeManagerRolePage: FC = () => ( - - - - -); diff --git a/features/change-role/change-manager-role.tsx b/features/change-role/change-manager-role.tsx deleted file mode 100644 index 5029fee50..000000000 --- a/features/change-role/change-manager-role.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ROLES } from 'consts/roles'; -import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; -import { ChangeRoleForm } from './change-role-form'; -import { Faq } from 'shared/components'; - -export const ChangeManagerRole = () => { - const key = useWeb3Key(); - - return ( - <> - - - - - - ); -}; diff --git a/features/change-role/change-reward-role-page.tsx b/features/change-role/change-reward-role-page.tsx deleted file mode 100644 index 566694299..000000000 --- a/features/change-role/change-reward-role-page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { FC } from 'react'; - -import { Layout } from 'shared/layout'; -import { RolesPageSwitcher } from 'shared/navigate'; -import { ChangeRewardRole } from './change-reward-role'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; - -export const ChangeRewardRolePage: FC = () => ( - - - - -); diff --git a/features/change-role/change-reward-role.tsx b/features/change-role/change-reward-role.tsx deleted file mode 100644 index 03627d764..000000000 --- a/features/change-role/change-reward-role.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; - -import { ChangeRoleForm } from './change-role-form'; -import { ROLES } from 'consts/roles'; -import { Faq } from 'shared/components'; - -export const ChangeRewardRole = () => { - const key = useWeb3Key(); - return ( - <> - - - - - - ); -}; diff --git a/features/change-role/change-role-form/change-role-form-loader.tsx b/features/change-role/change-role-form/change-role-form-loader.tsx index eaaf3c033..0a01418de 100644 --- a/features/change-role/change-role-form/change-role-form-loader.tsx +++ b/features/change-role/change-role-form/change-role-form-loader.tsx @@ -1,19 +1,21 @@ import { FC, PropsWithChildren } from 'react'; -import { useFormState } from 'react-hook-form'; -import { WhenLoaded } from 'shared/components'; -import { ChangeRoleFormInputType, useChangeRoleFormData } from './context'; +import { Form, FormLoader } from 'shared/hook-form/form-controller'; +import { useChangeRoleFlow } from './context'; import { Info } from './controls/info'; -export const ChangeRoleFormLoader: FC = ({ children }) => { - const { isLoading } = useFormState(); - const { loading, isManagerReset, isRewardsChange, isPropose } = - useChangeRoleFormData(); - - const isView = !(isManagerReset || isRewardsChange || isPropose); - - return ( - - {isView ? : children} - +const ChangeRoleFormGate: FC = ({ children }) => { + const flow = useChangeRoleFlow(); + return flow.action === 'view' ? ( +
+ + + ) : ( + <>{children} ); }; + +export const ChangeRoleFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/change-role/change-role-form/change-role-form.tsx b/features/change-role/change-role-form/change-role-form.tsx index 4af6e5377..09a2916f8 100644 --- a/features/change-role/change-role-form/change-role-form.tsx +++ b/features/change-role/change-role-form/change-role-form.tsx @@ -1,30 +1,35 @@ import { FC, memo } from 'react'; -import { ChangeRoleFormProvider } from './context'; - -import { FormBlock } from 'shared/components'; -import { FormControllerStyled } from 'shared/hook-form/form-controller'; +import { PATH } from 'consts/urls'; +import { BackButton, FormBlock } from 'shared/components'; +import { Form } from 'shared/hook-form/form-controller'; +import { ChangeRoleFormLoader } from './change-role-form-loader'; import { ChangeRoleFormInfo } from './change-role-form-info'; -import { ChangeRoleFormProviderProps } from './context'; +import { + ChangeRoleDataProvider, + ChangeRoleDataProviderProps, + ChangeRoleFormProvider, +} from './context'; import { AddressInput } from './controls/address-input'; import { Info } from './controls/info'; import { SubmitButton } from './controls/submit-button'; -import { ChangeRoleFormLoader } from './change-role-form-loader'; -// TODO: update layout title/subtitle -export const ChangeRoleForm: FC = memo((props) => { +export const ChangeRoleForm: FC = memo((props) => { return ( - - - - - - - - - - - - + + + + + +
+ + + + + +
+
+
+
); }); diff --git a/features/change-role/change-role-form/confirm-change-role-modal.tsx b/features/change-role/change-role-form/confirm-change-role-modal.tsx new file mode 100644 index 000000000..f01376b0b --- /dev/null +++ b/features/change-role/change-role-form/confirm-change-role-modal.tsx @@ -0,0 +1,94 @@ +import { Button, Modal, Text } from '@lidofinance/lido-ui'; + +import type { ModalComponentType } from 'providers/modal-provider'; +import { FC, useCallback, useMemo, useState } from 'react'; +import { Stack } from 'shared/components'; +import { ConfirmModalProps } from 'shared/hooks'; + +type Props = { + showRewards: boolean; + isProposal: boolean; + showRepropose: boolean; +}; + +type Step = 'rewards' | 'repropose'; + +export const ConfirmChangeRoleModal: ModalComponentType< + ConfirmModalProps & Props +> = ({ + showRewards, + isProposal, + showRepropose, + onConfirm, + onReject, + ...props +}) => { + const steps = useMemo( + () => + [showRewards && 'rewards', showRepropose && 'repropose'].filter( + Boolean, + ) as Step[], + [showRewards, showRepropose], + ); + + const [index, setIndex] = useState(0); + const current = steps[index]; + const isLast = index >= steps.length - 1; + + const onContinue = useCallback(() => { + if (isLast) onConfirm(); + else setIndex((i) => i + 1); + }, [isLast, onConfirm]); + + return ( + + + {current === 'rewards' ? ( + + ) : ( + + )} + + + + {current === 'rewards' && isProposal && ( + + The change doesn’t apply immediately. To complete the address + change, the owner of the new address must confirm the change. + + )} + + + + ); +}; + +const RewardsStep: FC<{ isProposal: boolean }> = ({ isProposal }) => ( + + + {isProposal + ? 'All rewards will be claimable to the proposed address' + : 'All rewards will be claimable to the new address'} + + + After changing the Rewards Address, all rewards and excess bond + accumulated on the bond balance can be claimed to the new Rewards Address. + In the event of validator withdrawal, the whole bond is also returned to + the new address. + + +); + +const ReproposeStep: FC = () => ( + + + Only most recent proposed address change is valid + + + When you propose a new address for change - the previous change proposal + is voided + + +); diff --git a/features/change-role/change-role-form/confirm-reproposed-modal.tsx b/features/change-role/change-role-form/confirm-reproposed-modal.tsx deleted file mode 100644 index d99c4f151..000000000 --- a/features/change-role/change-role-form/confirm-reproposed-modal.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Button, Modal, Text } from '@lidofinance/lido-ui'; - -import type { ModalComponentType } from 'providers/modal-provider'; -import { Stack } from 'shared/components'; -import { ConfirmModalProps } from 'shared/hooks'; - -export const ConfirmReproposeModal: ModalComponentType = ({ - onConfirm, - onReject, - ...props -}) => { - return ( - - - - - Only most recent proposed address change is valid - - - When you propose a new address for change - the previous change - proposal is voided. - - - - - - - ); -}; diff --git a/features/change-role/change-role-form/confirm-rewards-role-modal.tsx b/features/change-role/change-role-form/confirm-rewards-role-modal.tsx deleted file mode 100644 index dfe2b070b..000000000 --- a/features/change-role/change-role-form/confirm-rewards-role-modal.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Button, Modal, Text } from '@lidofinance/lido-ui'; - -import type { ModalComponentType } from 'providers/modal-provider'; -import { Stack } from 'shared/components'; -import { ConfirmModalProps } from 'shared/hooks'; - -export const ConfirmRewardsRoleModal: ModalComponentType = ({ - onConfirm, - onReject, - ...props -}) => { - return ( - - - - - All rewards will be claimable to the proposed address - - - After changing the Rewards Address, all rewards and excess bond - accumulated on the bond balance can be claimed to the new Rewards - address. In the event of validator withdrawal, the whole bond is - also returned to the new address. - - - - - - - The change doesn’t apply immediately. To complete the address - change, the owner of the new address must confirm the change - - - - - ); -}; diff --git a/features/change-role/change-role-form/context/change-role-data-provider.tsx b/features/change-role/change-role-form/context/change-role-data-provider.tsx new file mode 100644 index 000000000..a48825db6 --- /dev/null +++ b/features/change-role/change-role-form/context/change-role-data-provider.tsx @@ -0,0 +1,89 @@ +import { ROLES } from '@lidofinance/lido-csm-sdk'; +import { + KEY_INVITES, + KEY_OPERATOR_INFO, + KEY_OPERATOR_IS_OWNER, + useDappStatus, + useNodeOperatorId, + useOperatorInfo, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useChangeRoleMode, useInvalidate } from 'shared/hooks'; +import invariant from 'tiny-invariant'; +import { type ChangeRoleFormNetworkData } from './types'; +import { isAddressEqual } from 'viem'; + +const useChangeRoleFormNetworkData: NetworkData< + ChangeRoleFormNetworkData, + ROLES +> = (role) => { + const { address } = useDappStatus(); + invariant(address); + + const nodeOperatorId = useNodeOperatorId(); + const infoQuery = useOperatorInfo(nodeOperatorId); + + const info = infoQuery.data; + const isInfoLoading = infoQuery.isPending; + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([KEY_OPERATOR_INFO, KEY_OPERATOR_IS_OWNER, KEY_INVITES]); + }, [invalidate]); + + const currentAddress = + role === ROLES.REWARDS ? info?.rewardsAddress : info?.managerAddress; + const proposedAddress = + role === ROLES.REWARDS + ? info?.proposedRewardsAddress + : info?.proposedManagerAddress; + + const mode = useChangeRoleMode(role); + const canEdit = mode !== 'view'; + const extendedManagerPermissions = info?.extendedManagerPermissions; + + const invite = + proposedAddress && isAddressEqual(proposedAddress, address) + ? { + nodeOperatorId, + role, + } + : null; + + return { + data: { + address, + role, + currentAddress, + proposedAddress, + nodeOperatorId, + canEdit, + extendedManagerPermissions, + invite, + } as ChangeRoleFormNetworkData, + isPending: isInfoLoading, + revalidate, + }; +}; + +export const useChangeRoleFormData = useFormData; + +export type ChangeRoleDataProviderProps = { role: ROLES }; + +export const ChangeRoleDataProvider: FC< + PropsWithChildren +> = ({ children, role }) => { + const networkData = useChangeRoleFormNetworkData(role); + + return ( + + {children} + + ); +}; diff --git a/features/change-role/change-role-form/context/change-role-form-provider.tsx b/features/change-role/change-role-form/context/change-role-form-provider.tsx index 2d9ebbf0c..692c19467 100644 --- a/features/change-role/change-role-form/context/change-role-form-provider.tsx +++ b/features/change-role/change-role-form/context/change-role-form-provider.tsx @@ -1,64 +1,49 @@ -import { ROLES } from 'consts/roles'; -import { FC, PropsWithChildren, useMemo } from 'react'; +import { ROLES } from '@lidofinance/lido-csm-sdk'; +import { FC, PropsWithChildren } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormControllerRetry, + FormControllerProvider, + useFlowSubmit, + useFormDefaultValues, } from 'shared/hook-form/form-controller'; -import { type ChangeRoleFormInputType } from './types'; -import { useChangeRoleFormNetworkData } from './use-change-role-form-network-data'; -import { useChangeRoleSubmit } from './use-change-role-submit'; - -import { useFormData } from 'shared/hook-form/form-controller'; -import { type ChangeRoleFormNetworkData } from './types'; +import { useChangeRoleMode } from 'shared/hooks'; +import { + ChangeRoleFormNetworkData, + type ChangeRoleFormInputType, +} from './types'; +import { useChangeRoleFlowResolver } from './use-change-role-flow'; import { useChangeRoleValidation } from './use-change-role-validation'; -import { useGetDefaultValues } from './use-get-default-values'; - -export const useChangeRoleFormData = useFormData; export type ChangeRoleFormProviderProps = { role: ROLES }; export const ChangeRoleFormProvider: FC< PropsWithChildren > = ({ children, role }) => { - const [networkData, revalidate] = useChangeRoleFormNetworkData({ role }); - const validationResolver = useChangeRoleValidation(networkData); + const mode = useChangeRoleMode(role); + const resolver = useChangeRoleValidation(role); - const asyncDefaultValues = useGetDefaultValues(networkData); + const defaultValues = useFormDefaultValues< + ChangeRoleFormInputType, + ChangeRoleFormNetworkData + >((data) => ({ + intent: 'submit', + address: mode === 'managerReset' ? data.address : undefined, + })); const formObject = useForm({ - defaultValues: asyncDefaultValues, - resolver: validationResolver, + defaultValues, + resolver, mode: 'onChange', }); - const { retryEvent, retryFire } = useFormControllerRetry(); - - const { changeRole } = useChangeRoleSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - ChangeRoleFormInputType, - ChangeRoleFormNetworkData - > = useMemo( - () => ({ - onSubmit: changeRole, - retryEvent, - }), - [changeRole, retryEvent], - ); + const resolve = useChangeRoleFlowResolver(role); + const submitter = useFlowSubmit(resolve); return ( - - - {children} - - + + {children} + ); }; diff --git a/features/change-role/change-role-form/context/index.ts b/features/change-role/change-role-form/context/index.ts index 6f271ce68..83229a2d8 100644 --- a/features/change-role/change-role-form/context/index.ts +++ b/features/change-role/change-role-form/context/index.ts @@ -1,2 +1,4 @@ +export * from './change-role-data-provider'; export * from './change-role-form-provider'; export * from './types'; +export * from './use-change-role-flow'; diff --git a/features/change-role/change-role-form/context/types.ts b/features/change-role/change-role-form/context/types.ts index bf880e027..c4cec21b8 100644 --- a/features/change-role/change-role-form/context/types.ts +++ b/features/change-role/change-role-form/context/types.ts @@ -1,19 +1,24 @@ -import { ROLES } from 'consts/roles'; -import { LoadingRecord, NodeOperatorId } from 'types'; +import { + NodeOperatorId, + NodeOperatorInviteInfo, + ROLES, +} from '@lidofinance/lido-csm-sdk'; +import { Address } from 'viem'; + +export type ChangeRoleIntent = 'submit' | 'revoke' | 'accept'; export type ChangeRoleFormInputType = { - address?: string; - isRevoke: boolean; + address?: Address; + intent: ChangeRoleIntent; }; export type ChangeRoleFormNetworkData = { - address: string; + address: Address; role: ROLES; - nodeOperatorId?: NodeOperatorId; - currentAddress?: string; - proposedAddress?: string; - isManagerReset: boolean; - isRewardsChange: boolean; - isPropose: boolean; - loading: LoadingRecord<'info'>; + nodeOperatorId: NodeOperatorId; + extendedManagerPermissions: boolean; + currentAddress: Address; + proposedAddress: Address; + canEdit: boolean; + invite: Pick | null; }; diff --git a/features/change-role/change-role-form/context/use-change-role-flow.ts b/features/change-role/change-role-form/context/use-change-role-flow.ts new file mode 100644 index 000000000..a39d5a1ad --- /dev/null +++ b/features/change-role/change-role-form/context/use-change-role-flow.ts @@ -0,0 +1,124 @@ +import { type NodeOperatorShortInfo, ROLES } from '@lidofinance/lido-csm-sdk'; +import { useAppendOperator, useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useChangeRoleMode } from 'shared/hooks'; +import { zeroAddress } from 'viem'; +import { useConfirmChangeRoleModal } from '../hooks/use-confirm-modal'; +import { useTxModalStagesChangeRole } from '../hooks/use-tx-modal-stages-change-role'; +import { useChangeRoleFormData } from './change-role-data-provider'; +import { ChangeRoleFormInputType, ChangeRoleFormNetworkData } from './types'; + +export type ChangeRoleFlow = + | { action: 'view' } + | ({ action: 'manager-reset' } & Executable) + | ({ action: 'rewards-change' } & Executable) + | ({ action: 'propose' } & Executable) + | ({ action: 'accept' } & Executable); + +export const useChangeRoleFlowResolver = ( + role: ROLES, +): FlowResolver< + ChangeRoleFormInputType, + ChangeRoleFormNetworkData, + ChangeRoleFlow +> => { + const sdk = useSmSDK(); + const appendNO = useAppendOperator(); + const confirm = useConfirmChangeRoleModal(); + const mode = useChangeRoleMode(role); + const buildCallback = useTxModalStagesChangeRole(role); + + return useCallback( + (input, data) => { + if (input.intent === 'accept' && data.invite) { + return { + action: 'accept', + submit: async () => { + const { result } = await sdk.roles.confirmAddress({ + nodeOperatorId: data.nodeOperatorId, + role: data.role, + callback: buildCallback(input, data), + }); + if (result) appendNO(result); + }, + }; + } + + if (!data.canEdit) return { action: 'view' }; + + const action = + mode === 'managerReset' + ? ('manager-reset' as const) + : mode === 'rewardsChange' + ? ('rewards-change' as const) + : ('propose' as const); + + // TODO: split this flow into separate ones for better readability and maintainability + return { + action, + confirm: async () => { + if (input.intent !== 'submit') return true; + + const showRewards = + data.role === ROLES.REWARDS && + (action === 'propose' || action === 'rewards-change'); + const showRepropose = action === 'propose' && !!data.proposedAddress; + + if (!showRewards && !showRepropose) return true; + + return confirm({ + showRewards, + isProposal: action === 'propose', + showRepropose, + }); + }, + submit: async () => { + const address = + input.intent === 'revoke' + ? zeroAddress + : (input.address ?? zeroAddress); + + const callback = buildCallback(input, data); + + const params = { + address, + nodeOperatorId: data.nodeOperatorId, + callback, + }; + + let result: NodeOperatorShortInfo | undefined; + + switch (action) { + case 'rewards-change': + ({ result } = await sdk.roles.changeRewardsAddress(params)); + break; + case 'manager-reset': + ({ result } = await sdk.roles.resetManagerAddress(params)); + break; + case 'propose': + ({ result } = + data.role === ROLES.REWARDS + ? await sdk.roles.proposeRewardsAddress(params) + : await sdk.roles.proposeManagerAddress(params)); + break; + } + + if (result) { + appendNO(result); + } + }, + }; + }, + [sdk, appendNO, confirm, mode, buildCallback], + ); +}; + +export const useChangeRoleFlow = (): ChangeRoleFlow => { + const data = useChangeRoleFormData(true); + const resolve = useChangeRoleFlowResolver(data.role); + return resolve({} as ChangeRoleFormInputType, data); +}; diff --git a/features/change-role/change-role-form/context/use-change-role-form-network-data.tsx b/features/change-role/change-role-form/context/use-change-role-form-network-data.tsx deleted file mode 100644 index dffda9f01..000000000 --- a/features/change-role/change-role-form/context/use-change-role-form-network-data.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { ROLES } from 'consts/roles'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { useCallback, useMemo } from 'react'; -import { useAccount, useNodeOperatorInfo } from 'shared/hooks'; -import invariant from 'tiny-invariant'; -import { compareLowercase } from 'utils'; -import { type ChangeRoleFormNetworkData } from './types'; - -export const useChangeRoleFormNetworkData = ({ - role, -}: { - role: ROLES; -}): [ChangeRoleFormNetworkData, () => Promise] => { - const { address } = useAccount(); - invariant(address); - - const nodeOperatorId = useNodeOperatorId(); - const { - data: info, - update: updateInfo, - initialLoading: isInfoLoading, - } = useNodeOperatorInfo(nodeOperatorId); - - // TODO: force udpate info - const revalidate = useCallback(async () => { - await Promise.allSettled([updateInfo()]); - }, [updateInfo]); - - const loading = useMemo( - () => ({ - isInfoLoading, - }), - [isInfoLoading], - ); - - const currentAddress = - role === ROLES.REWARDS ? info?.rewardAddress : info?.managerAddress; - const proposedAddress = - role === ROLES.REWARDS - ? info?.proposedRewardAddress - : info?.proposedManagerAddress; - - const isManagerReset = - role === ROLES.MANAGER && - !info?.extendedManagerPermissions && - compareLowercase(info?.rewardAddress, address) && - !compareLowercase(info?.managerAddress, address); - - const isRewardsChange = - role === ROLES.REWARDS && - !!info?.extendedManagerPermissions && - compareLowercase(info.managerAddress, address); - - const isPropose = - !isManagerReset && - !isRewardsChange && - compareLowercase(currentAddress, address); - - return [ - { - address, - role, - currentAddress, - proposedAddress, - nodeOperatorId, - isManagerReset, - isRewardsChange, - isPropose, - loading, - }, - revalidate, - ]; -}; diff --git a/features/change-role/change-role-form/context/use-change-role-submit.ts b/features/change-role/change-role-form/context/use-change-role-submit.ts deleted file mode 100644 index a60ba5766..000000000 --- a/features/change-role/change-role-form/context/use-change-role-submit.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { useCallback } from 'react'; -import invariant from 'tiny-invariant'; - -import { AddressZero } from '@ethersproject/constants'; -import { ROLES } from 'consts/roles'; -import { useCSModuleWeb3, useSendTx } from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; -import { runWithTransactionLogger } from 'utils'; -import { ChangeRoleFormInputType, ChangeRoleFormNetworkData } from '.'; -import { - useConfirmReproposeModal, - useConfirmRewardsRoleModal, -} from '../hooks/use-confirm-modal'; -import { useTxModalStagesChangeRole } from '../hooks/use-tx-modal-stages-change-role'; - -type UseChangeRoleOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type ChangeRoleMethodParams = { - address: string; - nodeOperatorId: NodeOperatorId; -}; - -// encapsulates eth/steth/wsteth flows -const useChangeRoleTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async ( - { - role, - isManagerReset, - isRewardsChange, - }: { role: ROLES; isRewardsChange: boolean; isManagerReset: boolean }, - params: ChangeRoleMethodParams, - ) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - switch (true) { - case isRewardsChange: - return { - tx: await CSModuleWeb3.populateTransaction.changeNodeOperatorRewardAddress( - params.nodeOperatorId, - params.address, - ), - txName: 'changeNodeOperatorRewardAddress', - }; - case isManagerReset: - return { - tx: await CSModuleWeb3.populateTransaction.resetNodeOperatorManagerAddress( - params.nodeOperatorId, - ), - txName: 'resetNodeOperatorManagerAddress', - }; - case role === ROLES.REWARDS: - return { - tx: await CSModuleWeb3.populateTransaction.proposeNodeOperatorRewardAddressChange( - params.nodeOperatorId, - params.address, - ), - txName: 'proposeNodeOperatorRewardAddressChange', - }; - case role === ROLES.MANAGER: - return { - tx: await CSModuleWeb3.populateTransaction.proposeNodeOperatorManagerAddressChange( - params.nodeOperatorId, - params.address, - ), - txName: 'proposeNodeOperatorManagerAddressChange', - }; - default: { - throw new Error('Not implemented yet: true case'); - } - } - }, - [CSModuleWeb3], - ); -}; - -export const useChangeRoleSubmit = ({ - onConfirm, - onRetry, -}: UseChangeRoleOptions) => { - const { txModalStages } = useTxModalStagesChangeRole(); - - const getTx = useChangeRoleTx(); - const sendTx = useSendTx(); - - const confirmRepropose = useConfirmReproposeModal(); - const confirmRewardsRole = useConfirmRewardsRoleModal(); - - const changeRole = useCallback( - async ( - { address: addressRaw, isRevoke }: ChangeRoleFormInputType, - { - nodeOperatorId, - proposedAddress, - currentAddress, - role, - isPropose, - isManagerReset, - isRewardsChange, - }: ChangeRoleFormNetworkData, - ): Promise => { - const address = isRevoke ? AddressZero : addressRaw; - invariant(role, 'Role is not defined'); - invariant(address, 'Addess is not defined'); - invariant(currentAddress, 'CurrentAddess is not defined'); - invariant(nodeOperatorId, 'NodeOperatorId is not defined'); - - if ( - !isRevoke && - isPropose && - role === ROLES.REWARDS && - !(await confirmRewardsRole({})) - ) { - return false; - } - - if ( - !isRevoke && - isPropose && - proposedAddress && - !(await confirmRepropose({})) - ) { - return false; - } - - try { - txModalStages.sign({ - address, - currentAddress, - role, - isPropose, - isRevoke, - isRewardsChange, - isManagerReset, - }); - - const tx = await getTx( - { role, isRewardsChange, isManagerReset }, - { - nodeOperatorId, - address, - }, - ); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'ChangeRole signing', - () => sendTx(tx), - ); - - txModalStages.pending( - { - address, - currentAddress, - role, - isPropose, - isRevoke, - isRewardsChange, - isManagerReset, - }, - txHash, - ); - - await runWithTransactionLogger('ChangeRole block confirmation', waitTx); - - await onConfirm?.(); - - txModalStages.success( - { - address, - currentAddress, - role, - isPropose, - isRevoke, - isRewardsChange, - isManagerReset, - }, - txHash, - ); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [ - confirmRewardsRole, - confirmRepropose, - getTx, - txModalStages, - onConfirm, - sendTx, - onRetry, - ], - ); - - return { - changeRole, - }; -}; diff --git a/features/change-role/change-role-form/context/use-change-role-validation.ts b/features/change-role/change-role-form/context/use-change-role-validation.ts index 9cf6b2060..920d3c6d6 100644 --- a/features/change-role/change-role-form/context/use-change-role-validation.ts +++ b/features/change-role/change-role-form/context/use-change-role-validation.ts @@ -1,37 +1,38 @@ -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; +import { ROLES } from '@lidofinance/lido-csm-sdk'; import { - handleResolverValidationError, + useFormValidation, ValidationError, } from 'shared/hook-form/validation'; -import { useAwaitNetworkData } from 'shared/hooks'; +import { useChangeRoleMode } from 'shared/hooks'; import { compareLowercase } from 'utils'; +import { isAddress } from 'viem'; import type { ChangeRoleFormInputType, ChangeRoleFormNetworkData, } from './types'; -import { isAddress } from 'ethers/lib/utils.js'; -export const useChangeRoleValidation = ( - networkData: ChangeRoleFormNetworkData, -) => { - const dataPromise = useAwaitNetworkData(networkData); +export const useChangeRoleValidation = (role: ROLES) => { + const mode = useChangeRoleMode(role); - return useCallback>( - async (values) => { - try { - const { address, isRevoke } = values; + return useFormValidation( + 'address', + async ( + { address, intent }, + { currentAddress, proposedAddress }, + validate, + ) => { + const isSubmit = intent === 'submit'; - const { currentAddress, proposedAddress, isPropose } = - await dataPromise; - - if (!isRevoke && !isAddress(address ?? '')) { + await validate('address', () => { + if (isSubmit && !isAddress(address ?? '')) { throw new ValidationError('address', 'Specify a valid address'); } + }); + await validate('address', () => { if ( - !isRevoke && - isPropose && + isSubmit && + (mode === 'propose' || mode === 'rewardsChange') && compareLowercase(address, currentAddress) ) { throw new ValidationError( @@ -39,10 +40,12 @@ export const useChangeRoleValidation = ( 'Should not be same as current address', ); } + }); + await validate('address', () => { if ( - !isRevoke && - isPropose && + isSubmit && + mode === 'propose' && compareLowercase(address, proposedAddress) ) { throw new ValidationError( @@ -50,19 +53,7 @@ export const useChangeRoleValidation = ( 'Should not be same as proposed address', ); } - - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError( - error, - 'ChangeRoleForm', - 'address', - ); - } + }); }, - [dataPromise], ); }; diff --git a/features/change-role/change-role-form/context/use-get-default-values.tsx b/features/change-role/change-role-form/context/use-get-default-values.tsx deleted file mode 100644 index 870d5af29..000000000 --- a/features/change-role/change-role-form/context/use-get-default-values.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { useCallback, useMemo } from 'react'; -import { useAwaiter } from 'shared/hooks'; -import { ChangeRoleFormInputType, ChangeRoleFormNetworkData } from './types'; - -export const useGetDefaultValues = ({ - isManagerReset, - address, - loading: { isInfoLoading }, -}: ChangeRoleFormNetworkData) => { - const values: ChangeRoleFormInputType | undefined = useMemo(() => { - if (isInfoLoading) return undefined; - return { - isRevoke: false, - address: isManagerReset ? address : undefined, - }; - }, [address, isInfoLoading, isManagerReset]); - - const { awaiter } = useAwaiter(values); - - return useCallback(() => awaiter, [awaiter]); -}; diff --git a/features/change-role/change-role-form/controls/address-input.tsx b/features/change-role/change-role-form/controls/address-input.tsx index a2e87777e..201272bae 100644 --- a/features/change-role/change-role-form/controls/address-input.tsx +++ b/features/change-role/change-role-form/controls/address-input.tsx @@ -1,19 +1,24 @@ import { FormTitle } from 'shared/components'; import { AddressInputHookForm } from 'shared/hook-form/controls'; import { useRole } from '../hooks/use-role'; -import { useChangeRoleFormData } from '../context'; +import { useChangeRoleFlow, useChangeRoleFormData } from '../context'; +import { isAddressEqual } from 'viem'; export const AddressInput: React.FC = () => { - const { isManagerReset } = useChangeRoleFormData(); + const flow = useChangeRoleFlow(); + const { address, currentAddress } = useChangeRoleFormData(true); const role = useRole(); return ( <> - Specify a new {role} address + Specify a new {role} Address ); diff --git a/features/change-role/change-role-form/controls/info.tsx b/features/change-role/change-role-form/controls/info.tsx index 87edf5ecf..33da1b30e 100644 --- a/features/change-role/change-role-form/controls/info.tsx +++ b/features/change-role/change-role-form/controls/info.tsx @@ -1,45 +1,126 @@ +import { ROLES } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { ROLES_METADATA } from 'consts/roles'; import { FC, useCallback } from 'react'; import { useFormContext } from 'react-hook-form'; -import { Latice, TitledAddress, Warning } from 'shared/components'; +import { + IconTooltip, + Latice, + RoleActionsList, + Stack, + TitledAddress, + Warning, +} from 'shared/components'; import { SubmitButtonHookForm } from 'shared/hook-form/controls'; -import { ChangeRoleFormInputType, useChangeRoleFormData } from '../context'; +import { isAddressEqual } from 'viem'; +import { + type ChangeRoleFormInputType, + useChangeRoleFlow, + useChangeRoleFormData, +} from '../context'; import { useRole } from '../hooks/use-role'; +import { moduleMeta } from 'consts'; export const Info: FC = () => { - const role = useRole(); - const { currentAddress, proposedAddress, isPropose } = - useChangeRoleFormData(); + const roleTitle = useRole(); + const flow = useChangeRoleFlow(); + const { + currentAddress, + proposedAddress, + address, + extendedManagerPermissions, + role, + invite, + } = useChangeRoleFormData(true); const { setValue } = useFormContext(); const revokeHandle = useCallback(() => { - setValue('isRevoke', true); + setValue('intent', 'revoke'); + }, [setValue]); + + const acceptHandle = useCallback(() => { + setValue('intent', 'accept'); }, [setValue]); return ( <> + + {ROLES_METADATA[role].capitalizedTitle} Address + - - - {isPropose && ( - - Revoke - - )} - + + Current {roleTitle} Address + + } + /> + + } + address={currentAddress} + isYou={isAddressEqual(currentAddress, address)} + isOwner={ + extendedManagerPermissions + ? role === ROLES.MANAGER + : role === ROLES.REWARDS } - address={proposedAddress} /> + + {proposedAddress && ( + + + + {flow.action === 'propose' ? ( + + Cancel + + ) : ( + invite && ( + + Accept + + ) + )} + + } + address={proposedAddress} + isYou={isAddressEqual(proposedAddress, address)} + /> + + Action required + + +
    +
  1. + Connect to {moduleMeta.shortTitle} UI with the proposed + address +
  2. +
  3. + Go to Settings tab → Inbox requests to confirm the change +
  4. +
+
+
+ )}
); diff --git a/features/change-role/change-role-form/controls/submit-button.tsx b/features/change-role/change-role-form/controls/submit-button.tsx index d694e17f2..d02bd6bfd 100644 --- a/features/change-role/change-role-form/controls/submit-button.tsx +++ b/features/change-role/change-role-form/controls/submit-button.tsx @@ -2,30 +2,32 @@ import { useCallback } from 'react'; import { useFormContext } from 'react-hook-form'; import { Note } from 'shared/components'; import { SubmitButtonHookForm } from 'shared/hook-form/controls'; -import { ChangeRoleFormInputType, useChangeRoleFormData } from '../context'; +import { type ChangeRoleFormInputType, useChangeRoleFlow } from '../context'; import { useRole } from '../hooks/use-role'; export const SubmitButton = () => { const role = useRole(); - const { isPropose, isManagerReset } = useChangeRoleFormData(); + const flow = useChangeRoleFlow(); const { setValue } = useFormContext(); + // TODO: move this to somethere ? const clickHandle = useCallback(() => { - setValue('isRevoke', false); + setValue('intent', 'submit'); }, [setValue]); - const title = isManagerReset - ? `Reset ${role} address` - : isPropose - ? `Propose a new ${role} address` - : `Change ${role} address`; + const title = + flow.action === 'manager-reset' + ? `Reset ${role} Address` + : flow.action === 'propose' + ? `Propose a new ${role} Address` + : `Change ${role} Address`; return ( <> - + {title} - {isPropose && ( + {flow.action === 'propose' && ( To complete the address change, the owner of the new address must confirm the change diff --git a/features/change-role/change-role-form/hooks/use-confirm-modal.ts b/features/change-role/change-role-form/hooks/use-confirm-modal.ts index a556c9a87..29b947077 100644 --- a/features/change-role/change-role-form/hooks/use-confirm-modal.ts +++ b/features/change-role/change-role-form/hooks/use-confirm-modal.ts @@ -1,11 +1,8 @@ import { getUseConfirmModal } from 'shared/hooks'; -import { ConfirmReproposeModal } from '../confirm-reproposed-modal'; -import { ConfirmRewardsRoleModal } from '../confirm-rewards-role-modal'; +import { ConfirmChangeRoleModal } from '../confirm-change-role-modal'; -export const useConfirmReproposeModal = getUseConfirmModal( - ConfirmReproposeModal, -); - -export const useConfirmRewardsRoleModal = getUseConfirmModal( - ConfirmRewardsRoleModal, -); +export const useConfirmChangeRoleModal = getUseConfirmModal<{ + showRewards: boolean; + isProposal: boolean; + showRepropose: boolean; +}>(ConfirmChangeRoleModal); diff --git a/features/change-role/change-role-form/hooks/use-role.ts b/features/change-role/change-role-form/hooks/use-role.ts index 9a3098963..e39057765 100644 --- a/features/change-role/change-role-form/hooks/use-role.ts +++ b/features/change-role/change-role-form/hooks/use-role.ts @@ -1,7 +1,7 @@ -import { getRoleTitle } from 'shared/node-operator'; +import { ROLES_METADATA } from 'consts'; import { useChangeRoleFormData } from '../context'; export const useRole = () => { - const { role } = useChangeRoleFormData(); - return getRoleTitle(role); + const { role } = useChangeRoleFormData(true); + return ROLES_METADATA[role].capitalizedTitle; }; diff --git a/features/change-role/change-role-form/hooks/use-tx-modal-stages-change-role.tsx b/features/change-role/change-role-form/hooks/use-tx-modal-stages-change-role.tsx index 457241037..bc4c0b9ed 100644 --- a/features/change-role/change-role-form/hooks/use-tx-modal-stages-change-role.tsx +++ b/features/change-role/change-role-form/hooks/use-tx-modal-stages-change-role.tsx @@ -1,80 +1,140 @@ -import { ROLES } from 'consts/roles'; -import { capitalize } from 'lodash'; -import { getRoleTitle } from 'shared/node-operator'; +import { type NodeOperatorShortInfo, ROLES } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { ROLES_METADATA } from 'consts/roles'; +import { Address as AddressComponent, Stack } from 'shared/components'; +import { type ChangeRoleMode, useChangeRoleMode } from 'shared/hooks'; import { - TransactionModalTransitStage, + AfterAddressProposed, TxStagePending, TxStageSign, TxStageSuccess, - getGeneralTransactionModalStages, - useTransactionModalStage, + useTxStages, } from 'shared/transaction-modal'; +import { zeroAddress } from 'viem'; +import { buildAcceptInviteStages } from 'features/accept-invite/accept-invite-form/hooks/use-tx-modal-stages-accept-invite'; +import { + ChangeRoleFormInputType, + ChangeRoleFormNetworkData, +} from '../context/types'; -type Props = { - address: string; - currentAddress: string; - role: ROLES; - isManagerReset: boolean; - isRewardsChange: boolean; - isPropose: boolean; - isRevoke: boolean; -}; +const getTexts = ( + input: ChangeRoleFormInputType, + data: ChangeRoleFormNetworkData, + mode: ChangeRoleMode, +) => { + const address = + input.intent === 'revoke' ? zeroAddress : (input.address ?? zeroAddress); -// TODO: show address with
component -const getTexts = (props: Props) => { - return props.isManagerReset || props.isRewardsChange + return mode === 'managerReset' || mode === 'rewardsChange' ? { sign: { - title: `You are changing ${getRoleTitle(props.role)} address`, - description: `New address ${props.address}`, + title: `You are changing ${ROLES_METADATA[data.role].capitalizedTitle} Address`, + description: ( + + New {ROLES_METADATA[data.role].capitalizedTitle} Address is + + + + + ), }, success: { - title: `${capitalize(getRoleTitle(props.role))} address has been changed`, - description: `New address ${props.address}`, + title: `${ROLES_METADATA[data.role].capitalizedTitle} Address has been changed`, + description: ( + + New {ROLES_METADATA[data.role].capitalizedTitle} Address is + + + + + ), }, } - : props.isRevoke + : input.intent === 'revoke' ? { sign: { - title: `You are revoking request for ${getRoleTitle(props.role)} address change`, - description: `Address stays ${props.currentAddress}`, + title: `You are canceling request for ${ROLES_METADATA[data.role].capitalizedTitle} Address change`, + description: ( + + Address stays + + + + + ), }, success: { - title: `Proposed request for ${getRoleTitle(props.role)} address has been revoked`, - description: `Address stays ${props.currentAddress}`, + title: `Proposed request for ${ROLES_METADATA[data.role].capitalizedTitle} Address has been canceled`, + description: ( + + Address stays + + + + + ), }, } : { sign: { - title: `You are proposing ${getRoleTitle(props.role)} address change`, - description: `Proposed address ${props.address}`, + title: `You are proposing ${ROLES_METADATA[data.role].capitalizedTitle} Address change`, + description: ( + + Proposed address + + + + + ), }, success: { - title: `New ${getRoleTitle(props.role)} address has been proposed`, - description: `To complete the address change, the owner of the new address must confirm the change`, + title: `New ${ROLES_METADATA[data.role].capitalizedTitle} Address has been proposed`, + description: ( + <> +
+
+ + + ), }, }; }; -const getTxModalStagesChangeRole = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: (props: Props) => - transitStage(), +export const useTxModalStagesChangeRole = (role: ROLES) => { + const mode = useChangeRoleMode(role); - pending: (props: Props, txHash?: string) => - transitStage(), - - success: (props: Props, txHash?: string) => - transitStage( - , - { - isClosableOnLedger: true, - }, - ), -}); + return useTxStages< + ChangeRoleFormInputType, + ChangeRoleFormNetworkData, + NodeOperatorShortInfo + >( + (transitStage, input, data) => { + if (input.intent === 'accept') { + return buildAcceptInviteStages(transitStage, { + invite: { nodeOperatorId: data.nodeOperatorId, role: data.role }, + address: data.address, + }); + } -export const useTxModalStagesChangeRole = () => - useTransactionModalStage(getTxModalStagesChangeRole); + return { + sign: () => + transitStage(), + pending: (txHash) => + transitStage( + , + ), + success: (_result: NodeOperatorShortInfo, txHash) => + transitStage( + , + ), + }; + }, + [mode], + ); +}; diff --git a/features/change-role/claimer-form/claimer-form-loader.tsx b/features/change-role/claimer-form/claimer-form-loader.tsx new file mode 100644 index 000000000..97d5ffc5f --- /dev/null +++ b/features/change-role/claimer-form/claimer-form-loader.tsx @@ -0,0 +1,15 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useClaimerFlow } from './context'; +import { Info } from './controls/info'; + +const ClaimerFormGate: FC = ({ children }) => { + const flow = useClaimerFlow(); + return flow.action === 'view' ? : <>{children}; +}; + +export const ClaimerFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/change-role/claimer-form/claimer-form.tsx b/features/change-role/claimer-form/claimer-form.tsx new file mode 100644 index 000000000..81816978d --- /dev/null +++ b/features/change-role/claimer-form/claimer-form.tsx @@ -0,0 +1,29 @@ +import { FC, memo } from 'react'; + +import { PATH } from 'consts/urls'; +import { BackButton, FormBlock } from 'shared/components'; +import { Form } from 'shared/hook-form/form-controller'; +import { ClaimerFormLoader } from './claimer-form-loader'; +import { ClaimerDataProvider, ClaimerFormProvider } from './context'; +import { AddressInput } from './controls/address-input'; +import { Info } from './controls/info'; +import { SubmitButton } from './controls/submit-button'; + +export const ClaimerForm: FC = memo(() => { + return ( + + + + + +
+ + + + +
+
+
+
+ ); +}); diff --git a/features/change-role/claimer-form/context/claimer-data-provider.tsx b/features/change-role/claimer-form/context/claimer-data-provider.tsx new file mode 100644 index 000000000..82fb0a649 --- /dev/null +++ b/features/change-role/claimer-form/context/claimer-data-provider.tsx @@ -0,0 +1,51 @@ +import { + KEY_CUSTOM_REWARDS_CLAIMER, + useCustomRewardsClaimer, + useNodeOperatorId, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useCanEditClaimer, useInvalidate } from 'shared/hooks'; +import { zeroAddress } from 'viem'; +import { type ClaimerFormNetworkData } from './types'; + +const useClaimerFormNetworkData: NetworkData = () => { + const nodeOperatorId = useNodeOperatorId(); + const claimerQuery = useCustomRewardsClaimer(nodeOperatorId); + const canEdit = useCanEditClaimer(); + + const currentClaimerAddress = + claimerQuery.data === zeroAddress ? undefined : claimerQuery.data; + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([KEY_CUSTOM_REWARDS_CLAIMER]); + }, [invalidate]); + + return { + data: { + nodeOperatorId, + currentClaimerAddress, + canEdit, + } as ClaimerFormNetworkData, + isPending: claimerQuery.isPending, + revalidate, + }; +}; + +export const useClaimerFormData = useFormData; + +export const ClaimerDataProvider: FC = ({ children }) => { + const networkData = useClaimerFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/change-role/claimer-form/context/claimer-form-provider.tsx b/features/change-role/claimer-form/context/claimer-form-provider.tsx new file mode 100644 index 000000000..97bd16f7c --- /dev/null +++ b/features/change-role/claimer-form/context/claimer-form-provider.tsx @@ -0,0 +1,39 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, + useFormDefaultValues, +} from 'shared/hook-form/form-controller'; +import { ClaimerFormNetworkData, type ClaimerFormInputType } from './types'; +import { useClaimerFlowResolver } from './use-claimer-flow'; +import { useClaimerValidation } from './use-claimer-validation'; + +export const ClaimerFormProvider: FC = ({ children }) => { + const resolver = useClaimerValidation(); + + const defaultValues = useFormDefaultValues< + ClaimerFormInputType, + ClaimerFormNetworkData + >(() => ({ + isUnset: false, + address: undefined, + })); + + const formObject = useForm({ + defaultValues, + resolver, + mode: 'onChange', + }); + + const resolve = useClaimerFlowResolver(); + const submitter = useFlowSubmit(resolve); + + return ( + + + {children} + + + ); +}; diff --git a/features/change-role/claimer-form/context/index.ts b/features/change-role/claimer-form/context/index.ts new file mode 100644 index 000000000..0487d32ae --- /dev/null +++ b/features/change-role/claimer-form/context/index.ts @@ -0,0 +1,4 @@ +export * from './claimer-data-provider'; +export * from './claimer-form-provider'; +export * from './types'; +export * from './use-claimer-flow'; diff --git a/features/change-role/claimer-form/context/types.ts b/features/change-role/claimer-form/context/types.ts new file mode 100644 index 000000000..97c45e2c8 --- /dev/null +++ b/features/change-role/claimer-form/context/types.ts @@ -0,0 +1,13 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { Address } from 'viem'; + +export type ClaimerFormInputType = { + address?: Address; + isUnset: boolean; +}; + +export type ClaimerFormNetworkData = { + nodeOperatorId: NodeOperatorId; + currentClaimerAddress: Address | undefined; + canEdit: boolean; +}; diff --git a/features/change-role/claimer-form/context/use-claimer-flow.ts b/features/change-role/claimer-form/context/use-claimer-flow.ts new file mode 100644 index 000000000..67d787656 --- /dev/null +++ b/features/change-role/claimer-form/context/use-claimer-flow.ts @@ -0,0 +1,51 @@ +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { zeroAddress } from 'viem'; +import { useTxModalStagesClaimer } from '../hooks/use-tx-modal-stages-claimer'; +import { useClaimerFormData } from './claimer-data-provider'; +import { ClaimerFormInputType, ClaimerFormNetworkData } from './types'; + +export type ClaimerFlow = + | { action: 'view' } + | ({ action: 'set-claimer' } & Executable); + +export const useClaimerFlowResolver = (): FlowResolver< + ClaimerFormInputType, + ClaimerFormNetworkData, + ClaimerFlow +> => { + const sdk = useSmSDK(); + const buildCallback = useTxModalStagesClaimer(); + + return useCallback( + (input, data) => { + if (!data.canEdit) return { action: 'view' }; + + return { + action: 'set-claimer' as const, + submit: () => { + const claimerAddress = input.isUnset + ? zeroAddress + : (input.address ?? zeroAddress); + + return sdk.roles.setCustomRewardsClaimer({ + nodeOperatorId: data.nodeOperatorId, + claimerAddress, + callback: buildCallback(input, data), + }); + }, + }; + }, + [sdk, buildCallback], + ); +}; + +export const useClaimerFlow = (): ClaimerFlow => { + const resolve = useClaimerFlowResolver(); + const data = useClaimerFormData(true); + return resolve({} as ClaimerFormInputType, data); +}; diff --git a/features/change-role/claimer-form/context/use-claimer-validation.ts b/features/change-role/claimer-form/context/use-claimer-validation.ts new file mode 100644 index 000000000..09cddef67 --- /dev/null +++ b/features/change-role/claimer-form/context/use-claimer-validation.ts @@ -0,0 +1,31 @@ +import { + useFormValidation, + ValidationError, +} from 'shared/hook-form/validation'; +import { compareLowercase } from 'utils'; +import { isAddress } from 'viem'; +import type { ClaimerFormInputType, ClaimerFormNetworkData } from './types'; + +export const useClaimerValidation = () => { + return useFormValidation( + 'address', + async ({ address, isUnset }, { currentClaimerAddress }, validate) => { + if (isUnset) return; + + await validate('address', () => { + if (!isAddress(address ?? '')) { + throw new ValidationError('address', 'Specify a valid address'); + } + }); + + await validate('address', () => { + if (compareLowercase(address, currentClaimerAddress)) { + throw new ValidationError( + 'address', + 'Should not be same as current claimer', + ); + } + }); + }, + ); +}; diff --git a/features/change-role/claimer-form/controls/address-input.tsx b/features/change-role/claimer-form/controls/address-input.tsx new file mode 100644 index 000000000..658c4f205 --- /dev/null +++ b/features/change-role/claimer-form/controls/address-input.tsx @@ -0,0 +1,14 @@ +import { FormTitle } from 'shared/components'; +import { AddressInputHookForm } from 'shared/hook-form/controls'; + +export const AddressInput: React.FC = () => { + return ( + <> + Specify a new Rewards Claimer Address + + + ); +}; diff --git a/features/change-role/claimer-form/controls/info.tsx b/features/change-role/claimer-form/controls/info.tsx new file mode 100644 index 000000000..216fb51fc --- /dev/null +++ b/features/change-role/claimer-form/controls/info.tsx @@ -0,0 +1,62 @@ +import { FC, useCallback } from 'react'; +import { useFormContext } from 'react-hook-form'; +import { + IconTooltip, + Latice, + Stack, + TitledAddress, + TitledValue, +} from 'shared/components'; +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; +import { ClaimerFormInputType, useClaimerFormData } from '../context'; +import { Text } from '@lidofinance/lido-ui'; + +export const Info: FC = () => { + const { currentClaimerAddress, canEdit } = useClaimerFormData(true); + const { setValue } = useFormContext(); + + const unsetHandle = useCallback(() => { + setValue('isUnset', true); + }, [setValue]); + + const title = ( + + Current Rewards claimer + + + ); + + return ( + <> + + Rewards claimer + + + {currentClaimerAddress ? ( + + {title} + {canEdit && ( + + Unset + + )} + + } + address={currentClaimerAddress} + /> + ) : ( + + )} + + + ); +}; diff --git a/features/change-role/claimer-form/controls/submit-button.tsx b/features/change-role/claimer-form/controls/submit-button.tsx new file mode 100644 index 000000000..726c99705 --- /dev/null +++ b/features/change-role/claimer-form/controls/submit-button.tsx @@ -0,0 +1,20 @@ +import { FC, useCallback } from 'react'; +import { useFormContext } from 'react-hook-form'; +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; +import { ClaimerFormInputType } from '../context'; + +export const SubmitButton: FC = () => { + const { setValue } = useFormContext(); + + const clickHandle = useCallback(() => { + setValue('isUnset', false); + }, [setValue]); + + return ( + <> + + Set new Rewards Claimer Address + + + ); +}; diff --git a/features/change-role/claimer-form/hooks/use-tx-modal-stages-claimer.tsx b/features/change-role/claimer-form/hooks/use-tx-modal-stages-claimer.tsx new file mode 100644 index 000000000..56353f4a8 --- /dev/null +++ b/features/change-role/claimer-form/hooks/use-tx-modal-stages-claimer.tsx @@ -0,0 +1,67 @@ +import { Text } from '@lidofinance/lido-ui'; +import { Address as AddressComponent, Stack } from 'shared/components'; +import { + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import { zeroAddress } from 'viem'; +import { ClaimerFormInputType, ClaimerFormNetworkData } from '../context/types'; + +const getTexts = (input: ClaimerFormInputType) => { + const claimerAddress = input.isUnset + ? zeroAddress + : (input.address ?? zeroAddress); + + return input.isUnset + ? { + sign: { + title: 'You are unsetting Rewards claimer', + description: 'Rewards claimer delegation will be removed', + }, + success: { + title: 'Rewards claimer has been unset', + description: 'Rewards claimer delegation has been removed', + }, + } + : { + sign: { + title: 'You are setting Rewards Claimer Address', + description: ( + + New Rewards Claimer Address is + + + + + ), + }, + success: { + title: 'Rewards Claimer Address has been set', + description: ( + + New Rewards Claimer Address is + + + + + ), + }, + }; +}; + +export const useTxModalStagesClaimer = () => + useTxStages( + (transitStage, input) => ({ + sign: () => transitStage(), + pending: (txHash) => + transitStage( + , + ), + success: (_result: undefined, txHash) => + transitStage( + , + ), + }), + ); diff --git a/features/change-role/claimer-form/index.ts b/features/change-role/claimer-form/index.ts new file mode 100644 index 000000000..41d9b18d0 --- /dev/null +++ b/features/change-role/claimer-form/index.ts @@ -0,0 +1 @@ +export { ClaimerForm } from './claimer-form'; diff --git a/features/change-role/claimer-page.tsx b/features/change-role/claimer-page.tsx new file mode 100644 index 000000000..f9c32540b --- /dev/null +++ b/features/change-role/claimer-page.tsx @@ -0,0 +1,26 @@ +import { FAQ_ROLES } from 'faq'; +import { FC } from 'react'; +import { Faq } from 'shared/components'; +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; +import { Layout } from 'shared/layout'; +import { SettingsPageSwitcher } from 'shared/navigate'; +import { ClaimerForm } from './claimer-form'; + +export const ClaimerPage: FC = () => { + const key = useWeb3Key(); + + return ( + + + + + + + + ); +}; diff --git a/features/change-role/index.ts b/features/change-role/index.ts index 98c581841..033851661 100644 --- a/features/change-role/index.ts +++ b/features/change-role/index.ts @@ -1,4 +1,5 @@ -export * from './change-manager-role-page'; -export * from './change-manager-role'; -export * from './change-reward-role-page'; -export * from './change-reward-role'; +export { RolesPage } from './roles-page'; +export { RewardAddressPage } from './reward-address-page'; +export { ManagerAddressPage } from './manager-address-page'; +export { ClaimerPage } from './claimer-page'; +export { SplitsPage } from './splits-page'; diff --git a/features/change-role/manager-address-page.tsx b/features/change-role/manager-address-page.tsx new file mode 100644 index 000000000..5039205cb --- /dev/null +++ b/features/change-role/manager-address-page.tsx @@ -0,0 +1,27 @@ +import { ROLES } from '@lidofinance/lido-csm-sdk'; +import { FAQ_ROLES } from 'faq'; +import { FC } from 'react'; +import { Faq } from 'shared/components'; +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; +import { Layout } from 'shared/layout'; +import { SettingsPageSwitcher } from 'shared/navigate'; +import { ChangeRoleForm } from './change-role-form'; + +export const ManagerAddressPage: FC = () => { + const key = useWeb3Key(); + + return ( + + + + + + + + ); +}; diff --git a/features/change-role/reward-address-page.tsx b/features/change-role/reward-address-page.tsx new file mode 100644 index 000000000..fd9f25f44 --- /dev/null +++ b/features/change-role/reward-address-page.tsx @@ -0,0 +1,27 @@ +import { ROLES } from '@lidofinance/lido-csm-sdk'; +import { FAQ_ROLES } from 'faq'; +import { FC } from 'react'; +import { Faq } from 'shared/components'; +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; +import { Layout } from 'shared/layout'; +import { SettingsPageSwitcher } from 'shared/navigate'; +import { ChangeRoleForm } from './change-role-form'; + +export const RewardAddressPage: FC = () => { + const key = useWeb3Key(); + + return ( + + + + + + + + ); +}; diff --git a/features/change-role/roles-list/index.ts b/features/change-role/roles-list/index.ts new file mode 100644 index 000000000..8c2fa7997 --- /dev/null +++ b/features/change-role/roles-list/index.ts @@ -0,0 +1 @@ +export { RolesList } from './roles-list'; diff --git a/features/change-role/roles-list/role-row.tsx b/features/change-role/roles-list/role-row.tsx new file mode 100644 index 000000000..c19f63e6d --- /dev/null +++ b/features/change-role/roles-list/role-row.tsx @@ -0,0 +1,52 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { FC } from 'react'; +import { Address, OwnerChip, PendingChange, YouChip } from 'shared/components'; +import { LocalLink } from 'shared/navigate'; +import { RoleAddressColumn, RoleNameColumn, RoleRowStyle } from './styles'; + +type RoleRowProps = { + title: string; + address?: string; + proposedAddress?: string; + isYou?: boolean; + isOwner?: boolean; + canEdit?: boolean; + path: PATH; +}; + +export const RoleRow: FC = ({ + title, + address, + proposedAddress, + isYou, + isOwner, + canEdit = false, + path, +}) => { + const buttonLabel = canEdit ? (!address ? 'Set up' : 'Edit') : 'View'; + + return ( + + + + {title} + + {isYou && } + {isOwner && } + + + + {address &&
} + + {proposedAddress && } + + + + + + + ); +}; diff --git a/features/change-role/roles-list/roles-list.tsx b/features/change-role/roles-list/roles-list.tsx new file mode 100644 index 000000000..15985d127 --- /dev/null +++ b/features/change-role/roles-list/roles-list.tsx @@ -0,0 +1,85 @@ +import { Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { + useCustomRewardsClaimer, + useFeeSplits, + useNodeOperatorId, + useOperatorInfo, +} from 'modules/web3'; +import { FC } from 'react'; +import { FormBlock, Stack } from 'shared/components'; +import { + useCanEditClaimer, + useCanEditManagerRole, + useCanEditRewardsRole, + useCanEditSplits, +} from 'shared/hooks'; +import { useShowFlags } from 'shared/hooks/use-show-rule'; +import { zeroAddress } from 'viem'; +import { RoleRow } from './role-row'; +import { SplitterRow } from './splitter-row'; +import { Divider } from './styles'; + +export const RolesList: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: info } = useOperatorInfo(nodeOperatorId); + const { data: claimerAddress } = useCustomRewardsClaimer(nodeOperatorId); + const { data: feeSplits } = useFeeSplits(nodeOperatorId); + const { HAS_MANAGER_ROLE, HAS_REWARDS_ROLE } = useShowFlags(); + + const canEditRewards = !!useCanEditRewardsRole(); + const canEditManager = !!useCanEditManagerRole(); + const canEditClaimer = useCanEditClaimer(); + const canEditSplits = useCanEditSplits(); + + const isClaimerSet = !!claimerAddress && claimerAddress !== zeroAddress; + + return ( + + + Roles + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/features/change-role/roles-list/splitter-row.tsx b/features/change-role/roles-list/splitter-row.tsx new file mode 100644 index 000000000..90f0bbc3c --- /dev/null +++ b/features/change-role/roles-list/splitter-row.tsx @@ -0,0 +1,55 @@ +import { FeeSplit } from '@lidofinance/lido-csm-sdk'; +import { Button, Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { FC } from 'react'; +import { Address } from 'shared/components'; +import { LocalLink } from 'shared/navigate'; +import { + RoleAddressColumn, + RoleNameColumn, + RoleRowStyle, + SplitShare, + SplitterAddressRow, +} from './styles'; + +type SplitterRowProps = { + feeSplits?: FeeSplit[]; + path: PATH; + canEdit?: boolean; +}; + +const formatShare = (share: bigint) => { + const percent = Number(share) / 100; + return `${percent}%`; +}; + +export const SplitterRow: FC = ({ + feeSplits, + path, + canEdit, +}) => { + return ( + + + + Rewards splitter + + + + + {feeSplits?.map((split) => ( + +
+ {formatShare(split.share)} + + ))} + + + + + + + ); +}; diff --git a/features/change-role/roles-list/styles.ts b/features/change-role/roles-list/styles.ts new file mode 100644 index 000000000..dee98f186 --- /dev/null +++ b/features/change-role/roles-list/styles.ts @@ -0,0 +1,44 @@ +import styled from 'styled-components'; + +export const RoleRowStyle = styled.div` + display: flex; + gap: ${({ theme }) => theme.spaceMap.lg}px; + align-items: flex-start; + justify-content: flex-end; +`; + +export const RoleNameColumn = styled.div` + display: flex; + gap: ${({ theme }) => theme.spaceMap.sm}px; + align-items: center; + width: 180px; + flex-shrink: 0; + flex-wrap: wrap; +`; + +export const RoleAddressColumn = styled.div` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spaceMap.md}px; + flex: 1; + min-width: 0; + justify-content: center; +`; + +export const Divider = styled.hr` + border: none; + border-top: 1px solid var(--lido-color-border); + margin: 0; +`; + +export const SplitterAddressRow = styled.div` + display: flex; + gap: ${({ theme }) => theme.spaceMap.lg}px; + align-items: center; +`; + +export const SplitShare = styled.span` + color: var(--lido-color-textSecondary); + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; + line-height: ${({ theme }) => theme.fontSizesMap.lg}px; +`; diff --git a/features/change-role/roles-page.tsx b/features/change-role/roles-page.tsx new file mode 100644 index 000000000..b051a3a91 --- /dev/null +++ b/features/change-role/roles-page.tsx @@ -0,0 +1,26 @@ +import { FAQ_ROLES } from 'faq'; +import { FC } from 'react'; +import { Faq } from 'shared/components'; +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; +import { Layout } from 'shared/layout'; +import { SettingsPageSwitcher } from 'shared/navigate'; +import { RolesList } from './roles-list'; + +export const RolesPage: FC = () => { + const key = useWeb3Key(); + + return ( + + + + + + + + ); +}; diff --git a/features/change-role/splits-form/confirm-splits-modal.tsx b/features/change-role/splits-form/confirm-splits-modal.tsx new file mode 100644 index 000000000..603e3efdd --- /dev/null +++ b/features/change-role/splits-form/confirm-splits-modal.tsx @@ -0,0 +1,128 @@ +import { FeeSplit } from '@lidofinance/lido-csm-sdk'; +import { BASIS_POINTS_DENOMINATOR } from '@lidofinance/lido-ethereum-sdk'; +import { Button, Modal, Text } from '@lidofinance/lido-ui'; +import type { ModalComponentType } from 'providers/modal-provider'; +import { Address as AddressComponent, Stack } from 'shared/components'; +import { ConfirmModalProps } from 'shared/hooks'; +import styled from 'styled-components'; +import { formatPercent } from 'utils'; + +type ConfirmSplitsModalProps = ConfirmModalProps & { + feeSplits: FeeSplit[]; +}; + +const TableRow = styled.div` + display: flex; + justify-content: space-between; + align-items: normal; + gap: ${({ theme }) => theme.spaceMap.md}px; +`; + +const TableHeader = styled(TableRow)` + color: var(--lido-color-textSecondary); + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; +`; + +const AddressCell = styled.div` + display: flex; + align-items: center; + gap: ${({ theme }) => theme.spaceMap.xs}px; + min-width: 0; + flex: 1; +`; + +const ShareCell = styled.div` + white-space: nowrap; +`; + +export const ConfirmSplitsModal: ModalComponentType< + ConfirmSplitsModalProps +> = ({ onConfirm, onReject, feeSplits, ...props }) => { + const isRemoving = feeSplits.length === 0; + + return ( + + + + {isRemoving ? ( + <> + + Are you sure you want to stop splitting rewards? + + + All rewards will be sent to the following address + + + ) : ( + <> + + Are you sure you want to set the following addresses in the + splitter? + + + + Please note: + + +
    +
  • + Editing is disabled while you have unclaimed rewards +
  • +
  • Additional addresses receive rewards in stETH only
  • +
  • + Claiming is permissionless: anyone can execute the claim, + but rewards go to the configured addresses +
  • +
+
+
+ + )} +
+ + + +
Recipient
+
Share
+
+ {isRemoving ? ( + + + Operator bond + + + {formatPercent(BASIS_POINTS_DENOMINATOR, false, 2)} % + + + ) : ( + feeSplits.map((row) => ( + + + + + {formatPercent(row.share, false, 2)} % + + )) + )} +
+ + + + + +
+
+ ); +}; diff --git a/features/change-role/splits-form/context/index.ts b/features/change-role/splits-form/context/index.ts new file mode 100644 index 000000000..ee1e9ddf9 --- /dev/null +++ b/features/change-role/splits-form/context/index.ts @@ -0,0 +1,5 @@ +export * from './splits-data-provider'; +export * from './splits-form-provider'; +export * from './types'; +export * from './use-splits-flow'; +export * from './use-splits-validation'; diff --git a/features/change-role/splits-form/context/splits-data-provider.tsx b/features/change-role/splits-form/context/splits-data-provider.tsx new file mode 100644 index 000000000..98b31226b --- /dev/null +++ b/features/change-role/splits-form/context/splits-data-provider.tsx @@ -0,0 +1,66 @@ +import { + KEY_FEE_SPLITS, + useDappStatus, + useFeeSplits, + useNodeOperatorId, + useOperatorBalance, + useOperatorRewards, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useCanEditSplits, useInvalidate, useShowFlags } from 'shared/hooks'; +import invariant from 'tiny-invariant'; +import { type SplitsFormNetworkData } from './types'; + +const useSplitsFormNetworkData: NetworkData = () => { + const { address } = useDappStatus(); + invariant(address); + + const nodeOperatorId = useNodeOperatorId(); + const { data: currentFeeSplits, isPending: isFeeSplitsPending } = + useFeeSplits(nodeOperatorId); + const { data: rewards, isPending: isOperatorRewardsPending } = + useOperatorRewards(nodeOperatorId); + const { data: pendingToSplit, isPending: isBalancePending } = + useOperatorBalance(nodeOperatorId, (data) => data.pendingToSplit); + + const canEdit = useCanEditSplits(); + const { HAS_OWNER_ROLE: isOwner } = useShowFlags(); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([KEY_FEE_SPLITS]); + }, [invalidate]); + + return { + data: { + address, + nodeOperatorId, + currentFeeSplits, + pendingToSplit, + rewards, + canEdit, + isOwner, + } as SplitsFormNetworkData, + isPending: + isFeeSplitsPending || isBalancePending || isOperatorRewardsPending, + revalidate, + }; +}; + +export const useSplitsFormData = useFormData; + +export const SplitsDataProvider: FC = ({ children }) => { + const networkData = useSplitsFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/change-role/splits-form/context/splits-form-provider.tsx b/features/change-role/splits-form/context/splits-form-provider.tsx new file mode 100644 index 000000000..e517c8fa0 --- /dev/null +++ b/features/change-role/splits-form/context/splits-form-provider.tsx @@ -0,0 +1,53 @@ +import { FC, PropsWithChildren, useCallback } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, + useFormDefaultValues, +} from 'shared/hook-form/form-controller'; +import { SplitsShareTrigger } from './splits-share-trigger'; +import { SplitsFormInputType, SplitsFormNetworkData } from './types'; +import { useSplitsFlowResolver } from './use-splits-flow'; +import { useSplitsValidation } from './use-splits-validation'; + +export const SplitsFormProvider: FC = ({ children }) => { + const resolver = useSplitsValidation(); + + const defaultValues = useFormDefaultValues< + SplitsFormInputType, + SplitsFormNetworkData + >(({ currentFeeSplits }) => ({ + isEditing: false, + feeSplits: currentFeeSplits, + totalShare: 0n, + })); + + const formObject = useForm({ + defaultValues, + resolver, + mode: 'onChange', + }); + + const resolve = useSplitsFlowResolver(); + const submitter = useFlowSubmit(resolve); + + const handleReset = useCallback( + (args: SplitsFormInputType) => { + formObject.reset({ ...args, isEditing: false }); + }, + [formObject], + ); + + return ( + + + + {children} + + + ); +}; diff --git a/features/change-role/splits-form/context/splits-share-trigger.tsx b/features/change-role/splits-form/context/splits-share-trigger.tsx new file mode 100644 index 000000000..3c057aafd --- /dev/null +++ b/features/change-role/splits-form/context/splits-share-trigger.tsx @@ -0,0 +1,42 @@ +import { FC, useEffect } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { SplitsFormInputType } from './types'; +import { MAX_FEE_SPLITS_COUNT } from '@lidofinance/lido-csm-sdk'; + +export const SplitsShareTrigger: FC = () => { + const feeSplits = useWatch({ + name: 'feeSplits', + }); + + const totalShares = feeSplits?.reduce((p, s) => p + (s?.share ?? 0n), 0n); + + const { trigger, setValue, clearErrors } = + useFormContext(); + + useEffect(() => { + if (!feeSplits) return; + + if (feeSplits.length === 0) { + clearErrors(); + } + + for (let i = 0; i < feeSplits.length - 1; i++) { + void trigger([`feeSplits.${i}.recipient`, `feeSplits.${i}.share`]); + } + + for (let i = feeSplits.length; i <= MAX_FEE_SPLITS_COUNT; i++) { + clearErrors([`feeSplits.${i}.recipient`, `feeSplits.${i}.share`]); + } + + // trigger & clearErrors is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [feeSplits]); + + useEffect(() => { + setValue('totalShare', totalShares, { shouldValidate: true }); + // setValue is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [totalShares]); + + return null; +}; diff --git a/features/change-role/splits-form/context/types.ts b/features/change-role/splits-form/context/types.ts new file mode 100644 index 000000000..e73a46cf6 --- /dev/null +++ b/features/change-role/splits-form/context/types.ts @@ -0,0 +1,18 @@ +import { FeeSplit, NodeOperatorId, Rewards } from '@lidofinance/lido-csm-sdk'; +import { Address } from 'viem'; + +export type SplitsFormInputType = { + isEditing: boolean; + feeSplits: Partial[]; + totalShare: bigint; +}; + +export type SplitsFormNetworkData = { + address: Address; + nodeOperatorId: NodeOperatorId; + currentFeeSplits: FeeSplit[]; + rewards: Rewards; + pendingToSplit: bigint; + canEdit: boolean; + isOwner: boolean; +}; diff --git a/features/change-role/splits-form/context/use-splits-flow.ts b/features/change-role/splits-form/context/use-splits-flow.ts new file mode 100644 index 000000000..4bd415cc3 --- /dev/null +++ b/features/change-role/splits-form/context/use-splits-flow.ts @@ -0,0 +1,73 @@ +import { FeeSplit } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import invariant from 'tiny-invariant'; +import { useConfirmSplitsModal } from '../hooks/use-confirm-modal'; +import { useTxModalStagesSplits } from '../hooks/use-tx-modal-stages-splits'; +import { useSplitsFormData } from './splits-data-provider'; +import { SplitsFormInputType, SplitsFormNetworkData } from './types'; + +export type SplitsFlow = + | { action: 'view' } + | ({ action: 'set-splits' } & Executable); + +// eslint-disable-next-line func-style +function assertFeeSplits( + splits: Partial[], +): asserts splits is FeeSplit[] { + invariant( + splits.every((s) => !!s.share && !!s.recipient), + 'All splits must have address and share defined', + ); +} + +export const useSplitsFlowResolver = (): FlowResolver< + SplitsFormInputType, + SplitsFormNetworkData, + SplitsFlow +> => { + const sdk = useSmSDK(); + const confirmSplits = useConfirmSplitsModal(); + const buildCallback = useTxModalStagesSplits(); + + return useCallback( + (input, data) => { + if (!data.canEdit) return { action: 'view' }; + + return { + action: 'set-splits' as const, + confirm: async () => { + assertFeeSplits(input.feeSplits); + return confirmSplits({ feeSplits: input.feeSplits }); + }, + submit: () => { + assertFeeSplits(input.feeSplits); + invariant( + data.rewards, + 'Rewards data is required for submitting splits', + ); + const { shares, proof } = data.rewards; + + return sdk.roles.setFeeSplits({ + nodeOperatorId: data.nodeOperatorId, + feeSplits: input.feeSplits, + shares, + proof, + callback: buildCallback(input, data), + }); + }, + }; + }, + [sdk, confirmSplits, buildCallback], + ); +}; + +export const useSplitsFlow = (): SplitsFlow => { + const resolve = useSplitsFlowResolver(); + const data = useSplitsFormData(true); + return resolve({} as SplitsFormInputType, data); +}; diff --git a/features/change-role/splits-form/context/use-splits-validation.ts b/features/change-role/splits-form/context/use-splits-validation.ts new file mode 100644 index 000000000..cd59ddfa4 --- /dev/null +++ b/features/change-role/splits-form/context/use-splits-validation.ts @@ -0,0 +1,74 @@ +import { + useFormValidation, + validateAddress, + validatePercentShare, + ValidationError, +} from 'shared/hook-form/validation'; +import { compareLowercase } from 'utils'; +import type { SplitsFormInputType, SplitsFormNetworkData } from './types'; +import { + FeeSplit, + MAX_FEE_SPLITS_COUNT, + PERCENT_BASIS, +} from '@lidofinance/lido-csm-sdk'; + +export const splitsEqual = (a: Partial[], b: FeeSplit[]) => + a.length === b.length && + a.every( + (s, i) => + compareLowercase(s.recipient, b[i].recipient) && s.share === b[i].share, + ); + +export const useSplitsValidation = () => { + return useFormValidation( + 'feeSplits', + async ({ feeSplits, totalShare }, { currentFeeSplits }, validate) => { + await validate('feeSplits', () => { + if (splitsEqual(feeSplits, currentFeeSplits)) { + throw new ValidationError( + 'feeSplits', + 'No changes were made to the additional addresses', + ); + } + + if (feeSplits.length > MAX_FEE_SPLITS_COUNT) { + throw new ValidationError( + 'feeSplits', + `Maximum ${MAX_FEE_SPLITS_COUNT} additional addresses`, + ); + } + }); + + await validate('totalShare', () => { + if (totalShare > PERCENT_BASIS) { + throw new ValidationError( + 'totalShare', + "You've exceeded 100% of the total share", + ); + } + }); + + for (let i = 0; i < (feeSplits?.length ?? 0); i++) { + const { recipient, share } = feeSplits[i]; + + await validate(`feeSplits.${i}.recipient`, () => { + validateAddress(`feeSplits.${i}.recipient`, recipient); + + const duplicate = feeSplits.findIndex( + (s, j) => j < i && compareLowercase(s.recipient, recipient), + ); + if (duplicate >= 0) { + throw new ValidationError( + `feeSplits.${i}.recipient`, + 'Duplicate address', + ); + } + }); + + await validate(`feeSplits.${i}.share`, () => { + validatePercentShare(`feeSplits.${i}.share`, share); + }); + } + }, + ); +}; diff --git a/features/change-role/splits-form/controls/bond-row.tsx b/features/change-role/splits-form/controls/bond-row.tsx new file mode 100644 index 000000000..1af1626ba --- /dev/null +++ b/features/change-role/splits-form/controls/bond-row.tsx @@ -0,0 +1,15 @@ +import { FC } from 'react'; +import { useRestShare } from '../hooks/use-rest-share'; +import { BondRowView } from './split-row-view'; + +export const BondRow: FC = () => { + const share = useRestShare(); + + return ( + + ); +}; diff --git a/features/change-role/splits-form/controls/edit-info.tsx b/features/change-role/splits-form/controls/edit-info.tsx new file mode 100644 index 000000000..19f22624b --- /dev/null +++ b/features/change-role/splits-form/controls/edit-info.tsx @@ -0,0 +1,31 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { BondRow } from './bond-row'; + +export const EditInfo: FC = () => { + return ( + <> + + Set up addresses to split rewards to + + +
    +
  • Split rewards across up to 10 additional addresses
  • +
  • Additional addresses receive rewards in stETH only
  • +
  • + Claiming is permissionless: anyone can execute the claim, but rewards + go only to the configured addresses +
  • +
+ + + + + + This share decreases as you allocate shares to the addresses below + + + + ); +}; diff --git a/features/change-role/splits-form/controls/edit-splits.tsx b/features/change-role/splits-form/controls/edit-splits.tsx new file mode 100644 index 000000000..e814c004a --- /dev/null +++ b/features/change-role/splits-form/controls/edit-splits.tsx @@ -0,0 +1,63 @@ +import { MAX_FEE_SPLITS_COUNT } from '@lidofinance/lido-csm-sdk'; +import { ButtonIcon, Plus, Text } from '@lidofinance/lido-ui'; +import { FC, useCallback } from 'react'; +import { useFieldArray, useFormContext } from 'react-hook-form'; +import { Stack } from 'shared/components'; +import styled from 'styled-components'; +import { SplitsFormInputType } from '../context'; +import { SplitRow } from './split-row'; + +export const EditSplits: FC = () => { + const { control } = useFormContext(); + const { fields, append, remove } = useFieldArray({ + control, + name: 'feeSplits', + }); + + const handleAdd = useCallback(() => { + append({ recipient: undefined, share: undefined }); + }, [append]); + + const { formState } = useFormContext(); + const splitsError = formState.errors.feeSplits; + const rootError = + splitsError && 'root' in splitsError + ? splitsError.root + : splitsError && 'message' in splitsError + ? splitsError + : undefined; + + return ( + + + Additional addresses + + + {fields.map((field, index) => ( + + ))} + + {rootError?.message && ( + + {rootError.message} + + )} + + {fields.length < MAX_FEE_SPLITS_COUNT && ( + } + variant="text" + size="xs" + onClick={handleAdd} + data-testid="addSplitButton" + > + Add new address + + )} + + ); +}; + +const ButtonStyled = styled(ButtonIcon)` + width: fit-content; +`; diff --git a/features/change-role/splits-form/controls/split-row-view.tsx b/features/change-role/splits-form/controls/split-row-view.tsx new file mode 100644 index 000000000..e959efb87 --- /dev/null +++ b/features/change-role/splits-form/controls/split-row-view.tsx @@ -0,0 +1,85 @@ +import { ButtonIcon, Input, LockSmall } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { InputAddress, InputPercent, Stack } from 'shared/components'; +import styled from 'styled-components'; +import { Address } from 'viem'; + +const AddressColumn = styled.div` + flex: 1; + min-width: 0; +`; + +const ShareColumn = styled.div` + width: 90px; + flex-shrink: 0; +`; + +type SplitRowProps = { + title: string; + address: Address; + share: bigint; + locked?: boolean; +}; + +export const SplitRowView: FC = ({ + title, + address, + share, + locked, +}) => { + return ( + + + + + + + + {locked && ( + } + variant="text" + size="xs" + /> + )} + + ); +}; + +type BondRowProps = { + title: string; + description: string; + share: bigint; +}; + +export const BondRowView: FC = ({ + title, + description, + share, +}) => { + return ( + + + + + + + + + ); +}; + +const InputStyled = styled(Input)` + & span span { + transform: translateY(-10px); + font-weight: 700; + color: var(--lido-color-text); + } + & input { + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; + line-height: 1.668; + top: 11px; + } +`; diff --git a/features/change-role/splits-form/controls/split-row.tsx b/features/change-role/splits-form/controls/split-row.tsx new file mode 100644 index 000000000..333658ce5 --- /dev/null +++ b/features/change-role/splits-form/controls/split-row.tsx @@ -0,0 +1,87 @@ +import { ButtonIcon, Close, Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { useFormContext, useFormState } from 'react-hook-form'; +import { Stack } from 'shared/components'; +import { + AddressInputHookForm, + PercentInputHookForm, +} from 'shared/hook-form/controls'; +import styled from 'styled-components'; +import { SplitsFormInputType } from '../context/types'; + +const AddressColumn = styled.div` + flex: 1; + min-width: 0; +`; + +const ShareColumn = styled.div` + width: 90px; + flex-shrink: 0; +`; + +type SplitRowProps = { + index: number; + onRemove: (index: number) => void; +}; + +export const SplitRow: FC = ({ index, onRemove }) => { + const { errors } = useFormState>( + { + name: [ + `feeSplits.${index}.recipient`, + `feeSplits.${index}.share`, + `totalShare`, + ], + }, + ); + + const { clearErrors } = useFormContext(); + + const recipientError = + errors.feeSplits?.[index]?.recipient ?? + errors[`feeSplits.${index}.recipient`]; + const shareError = + errors.feeSplits?.[index]?.share ?? + errors[`feeSplits.${index}.share`] ?? + errors.totalShare; + const errorMessage = recipientError?.message || shareError?.message; + + return ( +
+ + + + + + { + clearErrors(`feeSplits.${index}.share`); + }} + error={!!shareError} + /> + + } + variant="ghost" + color="secondary" + size="xs" + onClick={() => onRemove(index)} + aria-label="Remove" + /> + + {errorMessage && ( + + {errorMessage} + + )} +
+ ); +}; diff --git a/features/change-role/splits-form/controls/submit-button.tsx b/features/change-role/splits-form/controls/submit-button.tsx new file mode 100644 index 000000000..8c9f6687e --- /dev/null +++ b/features/change-role/splits-form/controls/submit-button.tsx @@ -0,0 +1,36 @@ +import { FC, useCallback } from 'react'; +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; +import { + splitsEqual, + SplitsFormInputType, + useSplitsFormData, +} from '../context'; +import { Button } from '@lidofinance/lido-ui'; +import { useFormContext, useWatch } from 'react-hook-form'; + +export const SubmitButton: FC = () => { + const { currentFeeSplits } = useSplitsFormData(true); + const { reset } = useFormContext(); + + const feeSplits = useWatch({ + name: 'feeSplits', + }); + + const isUnchanged = splitsEqual(feeSplits ?? [], currentFeeSplits); + + const handleCancel = useCallback(() => { + reset(); + }, [reset]); + + return ( + <> + + {currentFeeSplits.length > 0 ? 'Apply changes' : 'Save splits'} + + + + + ); +}; diff --git a/features/change-role/splits-form/controls/view-splits.tsx b/features/change-role/splits-form/controls/view-splits.tsx new file mode 100644 index 000000000..73889c9d5 --- /dev/null +++ b/features/change-role/splits-form/controls/view-splits.tsx @@ -0,0 +1,109 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts'; +import { FC, useCallback } from 'react'; +import { useFormContext } from 'react-hook-form'; +import { Stack } from 'shared/components'; +import { WarningBlockStyle } from 'shared/components/warning-block/style'; +import { LocalLink } from 'shared/navigate'; +import { SplitsFormInputType, useSplitsFormData } from '../context'; +import { BondRow } from './bond-row'; +import { SplitRowView } from './split-row-view'; + +export const ViewSplits: FC = () => { + const { setValue } = useFormContext(); + const handleEdit = useCallback(() => setValue('isEditing', true), [setValue]); + const { currentFeeSplits, canEdit, rewards, pendingToSplit } = + useSplitsFormData(true); + + return ( + <> + {canEdit && + currentFeeSplits.length === 0 && + rewards.proof.length === 0 ? ( + + You can set up rewards splitting now. Please note that editing will + only be available after your first rewards are distributed. + + ) : canEdit && currentFeeSplits.length === 0 && rewards.available ? ( + + + You have unclaimed rewards. If you set up splitting now, unclaimed + rewards will be distributed using the new split settings. To keep + current distribution, claim your rewards first. + + + + + + ) : null} + + {currentFeeSplits.length > 0 && rewards.proof.length === 0 ? ( + + + Editing is disabled while your first rewards have not been + distributed yet + + + ) : currentFeeSplits.length > 0 && rewards.available ? ( + + + + Editing is disabled while you have unclaimed rewards. Claim + them in Bond & Rewards to continue. Unclaimed rewards will be + distributed using your current split settings. + + + + + + + ) : pendingToSplit ? ( + + + + Editing is disabled while there are pending shares to + distribute. Claim them in Bond & Rewards to continue. + + + + + + + ) : null} + + + Rewards splitter settings + + + + + {currentFeeSplits.length > 0 && ( + + + Additional addresses + + {currentFeeSplits.map((split, i) => ( + + ))} + + )} + + {canEdit && ( + + )} + + ); +}; diff --git a/features/change-role/splits-form/hooks/use-confirm-modal.ts b/features/change-role/splits-form/hooks/use-confirm-modal.ts new file mode 100644 index 000000000..9fe695636 --- /dev/null +++ b/features/change-role/splits-form/hooks/use-confirm-modal.ts @@ -0,0 +1,4 @@ +import { getUseConfirmModal } from 'shared/hooks'; +import { ConfirmSplitsModal } from '../confirm-splits-modal'; + +export const useConfirmSplitsModal = getUseConfirmModal(ConfirmSplitsModal); diff --git a/features/change-role/splits-form/hooks/use-rest-share.ts b/features/change-role/splits-form/hooks/use-rest-share.ts new file mode 100644 index 000000000..9117e189b --- /dev/null +++ b/features/change-role/splits-form/hooks/use-rest-share.ts @@ -0,0 +1,14 @@ +import { PERCENT_BASIS } from '@lidofinance/lido-csm-sdk'; +import { useWatch } from 'react-hook-form'; +import { bigMax } from 'utils'; +import { SplitsFormInputType } from '../context'; + +export const useRestShare = () => { + const totalShare = useWatch({ + name: 'totalShare', + }); + + const share = bigMax(0n, PERCENT_BASIS - totalShare); + + return share; +}; diff --git a/features/change-role/splits-form/hooks/use-tx-modal-stages-splits.tsx b/features/change-role/splits-form/hooks/use-tx-modal-stages-splits.tsx new file mode 100644 index 000000000..d732fbae7 --- /dev/null +++ b/features/change-role/splits-form/hooks/use-tx-modal-stages-splits.tsx @@ -0,0 +1,45 @@ +import { + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import { SplitsFormInputType, SplitsFormNetworkData } from '../context/types'; + +const getTexts = (input: SplitsFormInputType) => + input.feeSplits.length === 0 + ? { + sign: { + title: 'You are removing fee splitter', + description: 'All rewards will go to the Rewards Address', + }, + success: { + title: 'Fee splitter has been removed', + description: 'All rewards will go to the Rewards Address', + }, + } + : { + sign: { + title: 'You are updating fee splitter configuration', + description: `Setting ${input.feeSplits.length} additional recipient${input.feeSplits.length > 1 ? 's' : ''}`, + }, + success: { + title: 'Fee splitter configuration has been updated', + description: `${input.feeSplits.length} additional recipient${input.feeSplits.length > 1 ? 's' : ''} configured`, + }, + }; + +export const useTxModalStagesSplits = () => + useTxStages( + (transitStage, input) => ({ + sign: () => transitStage(), + pending: (txHash) => + transitStage( + , + ), + success: (_result: undefined, txHash) => + transitStage( + , + ), + }), + ); diff --git a/features/change-role/splits-form/index.ts b/features/change-role/splits-form/index.ts new file mode 100644 index 000000000..e733fe202 --- /dev/null +++ b/features/change-role/splits-form/index.ts @@ -0,0 +1 @@ +export { SplitsForm } from './splits-form'; diff --git a/features/change-role/splits-form/splits-form-loader.tsx b/features/change-role/splits-form/splits-form-loader.tsx new file mode 100644 index 000000000..e0a2c2e5f --- /dev/null +++ b/features/change-role/splits-form/splits-form-loader.tsx @@ -0,0 +1,13 @@ +import { FC, PropsWithChildren } from 'react'; +import { useWatch } from 'react-hook-form'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { SplitsFormInputType } from './context'; +import { ViewSplits } from './controls/view-splits'; + +export const SplitsFormLoader: FC = ({ children }) => { + const isEditing = useWatch({ + name: 'isEditing', + }); + + return {isEditing ? children : }; +}; diff --git a/features/change-role/splits-form/splits-form.tsx b/features/change-role/splits-form/splits-form.tsx new file mode 100644 index 000000000..d97273d1e --- /dev/null +++ b/features/change-role/splits-form/splits-form.tsx @@ -0,0 +1,28 @@ +import { PATH } from 'consts/urls'; +import { FC, memo } from 'react'; +import { BackButton, FormBlock } from 'shared/components'; +import { Form } from 'shared/hook-form/form-controller'; +import { SplitsDataProvider, SplitsFormProvider } from './context'; +import { EditInfo } from './controls/edit-info'; +import { EditSplits } from './controls/edit-splits'; +import { SubmitButton } from './controls/submit-button'; +import { SplitsFormLoader } from './splits-form-loader'; + +export const SplitsForm: FC = memo(() => { + return ( + + + + + +
+ + + + +
+
+
+
+ ); +}); diff --git a/features/change-role/splits-page.tsx b/features/change-role/splits-page.tsx new file mode 100644 index 000000000..c7a4c9c40 --- /dev/null +++ b/features/change-role/splits-page.tsx @@ -0,0 +1,26 @@ +import { FAQ_ROLES } from 'faq'; +import { FC } from 'react'; +import { Faq } from 'shared/components'; +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; +import { Layout } from 'shared/layout'; +import { SettingsPageSwitcher } from 'shared/navigate'; +import { SplitsForm } from './splits-form'; + +export const SplitsPage: FC = () => { + const key = useWeb3Key(); + + return ( + + + + + + + + ); +}; diff --git a/features/claim-bond/claim-bond-form/claim-bond-form-info-splitters.tsx b/features/claim-bond/claim-bond-form/claim-bond-form-info-splitters.tsx new file mode 100644 index 000000000..5f3193637 --- /dev/null +++ b/features/claim-bond/claim-bond-form/claim-bond-form-info-splitters.tsx @@ -0,0 +1,94 @@ +import { FeeSplit, PERCENT_BASIS, TOKENS } from '@lidofinance/lido-csm-sdk'; +import { AccordionTransparent, Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Address, IconTooltip, Stack } from 'shared/components'; +import { FormatToken } from 'shared/formatters'; +import styled from 'styled-components'; + +type Props = { + feeSplits: FeeSplit[]; + amount: bigint; +}; + +const splitAmount = (amount: bigint, share: bigint) => + (amount * share) / PERCENT_BASIS; + +export const ClaimBondFormInfoSplitters: FC = ({ + feeSplits, + amount, +}) => { + const total = feeSplits.reduce( + (sum, s) => sum + splitAmount(amount, s.share), + 0n, + ); + + return ( + +
+ Splitter addresses ({feeSplits.length}) will receive + +
+ + + + + } + > + + {feeSplits.map((split) => ( + +
+ + + ))} + + + ); +}; + +const AccordionStyle = styled(AccordionTransparent)` + padding: 0; + + & > div:first-child > div:first-child { + color: var(--lido-color-textSecondary); + font-weight: 400; + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; + line-height: 1.6em; + + > div { + margin: 0; + } + } + + & > div:first-child span:has(> svg) { + opacity: 1; + vertical-align: bottom; + margin-block: -3px; + display: inline-block; + } + + & > div + div > div { + padding-top: ${({ theme }) => theme.spaceMap.sm}px; + } +`; diff --git a/features/claim-bond/claim-bond-form/claim-bond-form-info.tsx b/features/claim-bond/claim-bond-form/claim-bond-form-info.tsx index 3c5994f42..4140917a0 100644 --- a/features/claim-bond/claim-bond-form/claim-bond-form-info.tsx +++ b/features/claim-bond/claim-bond-form/claim-bond-form-info.tsx @@ -1,54 +1,96 @@ -import { Zero } from '@ethersproject/constants'; +import { STETH_ROUNDING_THRESHOLD, TOKENS } from '@lidofinance/lido-csm-sdk'; import { DataTable, DataTableRow } from '@lidofinance/lido-ui'; -import { TOKENS } from 'consts/tokens'; -import { useWatch } from 'react-hook-form'; -import { FormatToken } from 'shared/formatters'; -import styled from 'styled-components'; -import { ClaimBondFormInputType, useClaimBondFormData } from './context'; -import { useBondReceiveAmount } from './hooks/use-bond-receive-amount'; import { Address } from 'shared/components'; -import { - AddressContainerStyle, - AddressStyle, -} from 'shared/components/address/styles'; +import { FormatToken } from 'shared/formatters'; +import { ClaimBondFormInfoSplitters } from './claim-bond-form-info-splitters'; +import { useClaimBondFormData } from './context'; +import { useClaimBreakdown } from './hooks/use-claim-breakdown'; export const ClaimBondFormInfo = () => { - const { rewardsAddress } = useClaimBondFormData(); - const [token, amount, claimRewards] = useWatch< - ClaimBondFormInputType, - ['token', 'amount', 'claimRewards'] - >({ - name: ['token', 'amount', 'claimRewards'], - }); - - const bondReceive = useBondReceiveAmount(); + const { rewardsAddress, feeSplits } = useClaimBondFormData(true); + const { + coverAmount, + splittableGross, + splittable, + toRA, + toRAToken, + token, + bondDelta, + debtBurned, + debtRemain, + includesRewards, + hasSplits, + isRewardsToBond, + } = useClaimBreakdown(); return ( - - - Rewards Address ( -
) will receive - - } - > - - - {claimRewards && ( - - + + {includesRewards && coverAmount > STETH_ROUNDING_THRESHOLD && ( + + + + )} + {includesRewards && debtBurned > 0n && ( + + + + )} + {debtRemain > 0n && ( + + + + )} + {hasSplits && splittable > 0n && ( + + )} + {toRA > 0n && ( + + Rewards Address ( +
+ ) will receive + + } + help="The recipient of the claim is the Rewards Address. You can change the Rewards Address on the Settings tab." + > + + + )} + {bondDelta > 0n && ( + + + + )} + {bondDelta < 0n && ( + + )} ); }; - -const AddressStyled = styled.div` - ${AddressContainerStyle} { - display: inline-flex; - } - ${AddressStyle} { - font-weight: bold; - } -`; diff --git a/features/claim-bond/claim-bond-form/claim-bond-form-loader.tsx b/features/claim-bond/claim-bond-form/claim-bond-form-loader.tsx new file mode 100644 index 000000000..accd40545 --- /dev/null +++ b/features/claim-bond/claim-bond-form/claim-bond-form-loader.tsx @@ -0,0 +1,22 @@ +import { FC, PropsWithChildren } from 'react'; +import { NoAccessNotice } from 'shared/components'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useClaimBondFlow } from './context'; +import { EmptyState } from './controls/empty-state'; + +const ClaimBondFormGate: FC = ({ children }) => { + const flow = useClaimBondFlow(); + + if (flow.action === 'no-access') + return ; + + if (flow.action === 'nothing') return ; + + return <>{children}; +}; + +export const ClaimBondFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/claim-bond/claim-bond-form/claim-bond-form.tsx b/features/claim-bond/claim-bond-form/claim-bond-form.tsx index ef4ff936a..338a40530 100644 --- a/features/claim-bond/claim-bond-form/claim-bond-form.tsx +++ b/features/claim-bond/claim-bond-form/claim-bond-form.tsx @@ -1,32 +1,36 @@ import { FC, memo } from 'react'; -import { ClaimBondFormProvider } from './context'; +import { ClaimBondDataProvider, ClaimBondFormProvider } from './context'; -import { FormBlock } from 'shared/components'; -import { - BaseFormLoader, - FormControllerStyled, -} from 'shared/hook-form/form-controller'; +import { FormBlock, Stack } from 'shared/components'; +import { Form } from 'shared/hook-form/form-controller'; import { ClaimBondFormInfo } from './claim-bond-form-info'; +import { ClaimBondFormLoader } from './claim-bond-form-loader'; import { AmountInput } from './controls/amount-input'; import { SourceSelect } from './controls/source-select'; +import { SourcesInfo } from './controls/sources-info'; import { SubmitButton } from './controls/submit-button'; import { TokenSelect } from './controls/token-select'; export const ClaimBondForm: FC = memo(() => { return ( - - - - - - - - - - - - - + + + + + + +
+ + + + + + +
+
+
+
+
); }); diff --git a/features/claim-bond/claim-bond-form/context/claim-bond-data-provider.tsx b/features/claim-bond/claim-bond-form/context/claim-bond-data-provider.tsx new file mode 100644 index 000000000..5f680ae7f --- /dev/null +++ b/features/claim-bond/claim-bond-form/context/claim-bond-data-provider.tsx @@ -0,0 +1,159 @@ +import { convertEthToShares, TOKENS } from '@lidofinance/lido-csm-sdk'; +import { MAX_ETH_AMOUNT } from 'consts/tokens'; +import { + KEY_OPERATOR_BALANCE, + KEY_OPERATOR_REWARDS, + useFeeSplits, + useIsContract, + useNodeOperatorId, + useOperatorBalance, + useOperatorInfo, + useOperatorRewards, + useSmStatus, + useStethPoolData, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import { bigMax, calculateAvailableToClaim } from 'utils'; +import { + CLAIM_OPTION, + type ClaimBondFormNetworkData, + type MaxValues, +} from './types'; + +const limitMaxEth = (value: bigint) => + value > MAX_ETH_AMOUNT ? MAX_ETH_AMOUNT : value; + +const useClaimBondFormNetworkData: NetworkData< + ClaimBondFormNetworkData +> = () => { + const nodeOperatorId = useNodeOperatorId(); + + const bondQuery = useOperatorBalance(nodeOperatorId); + const rewardsQuery = useOperatorRewards(nodeOperatorId); + + const bond = bondQuery.data; + const rewards = rewardsQuery.data; + + const isBondLoading = bondQuery.isPending; + const isRewardsLoading = rewardsQuery.isPending; + + const { data: poolData, isPending: isPoolDataLoading } = useStethPoolData(); + + const { data: nodeOperator, isPending: isInfoLoading } = + useOperatorInfo(nodeOperatorId); + + const rewardsAddress = nodeOperator?.rewardsAddress; + + const { data: isContract, isPending: isContractLoading } = + useIsContract(rewardsAddress); + + const { data: status, isPending: isStatusLoading } = useSmStatus(); + + const { data: feeSplits, isPending: isFeeSplitsLoading } = + useFeeSplits(nodeOperatorId); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([KEY_OPERATOR_BALANCE, KEY_OPERATOR_REWARDS]); + }, [invalidate]); + + const isPending = + isBondLoading || + isRewardsLoading || + isPoolDataLoading || + isInfoLoading || + isContractLoading || + isStatusLoading || + isFeeSplitsLoading; + + const claimableBond = calculateAvailableToClaim({ bond, feeSplits }); + const claimableBondAndRewards = calculateAvailableToClaim({ + bond, + rewards, + feeSplits, + }); + + const claimableMaxValues: MaxValues | undefined = poolData + ? { + [TOKENS.eth]: [ + limitMaxEth(claimableBond), + limitMaxEth(claimableBondAndRewards), + ], + [TOKENS.steth]: [claimableBond, claimableBondAndRewards], + [TOKENS.wsteth]: [ + convertEthToShares(claimableBond, poolData), + convertEthToShares(claimableBondAndRewards, poolData), + ], + } + : undefined; + + const keysInsufficient = bond ? bigMax(0n, bond.required - bond.current) : 0n; + const realInsufficient = bond + ? bigMax(0n, bond.required + bond.locked + bond.debt - bond.current) + : 0n; + const realExcess = bond + ? bigMax(0n, bond.current - bond.required - bond.locked - bond.debt) + : 0n; + const rewardsRemainder = rewards + ? bigMax(0n, rewards.available - realInsufficient) + : 0n; + const totalShare = feeSplits?.reduce((sum, s) => sum + s.share, 0n) ?? 0n; + + // ALL_TO_RA collapses to REWARDS_TO_BOND whenever nothing reaches the Rewards + // Address (rewards fully absorbed by forKeys/locked/debt, or splitters take + // 100%). In that case the Rewards-to-Bond option carries the same tx and we + // hide the duplicate. REWARDS_TO_BOND is offered whenever rewards exist — + // pulling them into bond is useful even without claimable excess. + const availableOptions = [ + rewards?.available && + claimableBondAndRewards > 0n && + CLAIM_OPTION.ALL_TO_RA, + claimableBond > 0n && CLAIM_OPTION.BOND_TO_RA, + rewards?.available && CLAIM_OPTION.REWARDS_TO_BOND, + ].filter((o): o is CLAIM_OPTION => !!o); + + return { + data: { + nodeOperatorId, + bond, + rewards, + poolData, + rewardsAddress, + isContract, + isPaused: status?.isPausedAccounting, + availableOptions, + feeSplits, + calculation: { + claimableBond, + claimableBondAndRewards, + claimableMaxValues, + keysInsufficient, + realInsufficient, + realExcess, + rewardsRemainder, + totalShare, + }, + } as ClaimBondFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useClaimBondFormData = useFormData; + +export const ClaimBondDataProvider: FC = ({ children }) => { + const networkData = useClaimBondFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/claim-bond/claim-bond-form/context/claim-bond-form-provider.tsx b/features/claim-bond/claim-bond-form/context/claim-bond-form-provider.tsx index 4a1c46656..6b931655c 100644 --- a/features/claim-bond/claim-bond-form/context/claim-bond-form-provider.tsx +++ b/features/claim-bond/claim-bond-form/context/claim-bond-form-provider.tsx @@ -1,60 +1,37 @@ -import { FC, PropsWithChildren, useMemo } from 'react'; +import { FC, PropsWithChildren } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormControllerRetry, - useFormData, + FormControllerProvider, + useFlowSubmit, } from 'shared/hook-form/form-controller'; -import { ClaimBondFormNetworkData, type ClaimBondFormInputType } from './types'; -import { useClaimBondFormNetworkData } from './use-claim-bond-form-network-data'; -import { useClaimBondSubmit } from './use-claim-bond-submit'; +import { ClaimBondUpdater } from './claim-bond-updater'; +import { type ClaimBondFormInputType } from './types'; +import { useClaimBondFlowResolver } from './use-claim-bond-flow'; +import { useClaimBondDefaultValues } from './use-claim-bond-default-values'; import { useClaimBondValidation } from './use-claim-bond-validation'; -import { useFormRevalidate } from './use-form-revalidate'; -import { useGetDefaultValues } from './use-get-default-values'; - -export const useClaimBondFormData = useFormData; export const ClaimBondFormProvider: FC = ({ children }) => { - const [networkData, revalidate] = useClaimBondFormNetworkData(); - const validationResolver = useClaimBondValidation(networkData); - - const asyncDefaultValues = useGetDefaultValues(networkData); + const resolver = useClaimBondValidation(); + const defaultValues = useClaimBondDefaultValues(); const formObject = useForm({ - defaultValues: asyncDefaultValues, - resolver: validationResolver, + defaultValues, + resolver, mode: 'onChange', }); - useFormRevalidate(formObject); - - const { retryEvent, retryFire } = useFormControllerRetry(); - - const { claimBond } = useClaimBondSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - ClaimBondFormInputType, - ClaimBondFormNetworkData - > = useMemo( - () => ({ - onSubmit: claimBond, - retryEvent, - }), - [claimBond, retryEvent], - ); + const submitter = useFlowSubmit(useClaimBondFlowResolver()); return ( - - - {children} - - + + + {children} + ); }; diff --git a/features/claim-bond/claim-bond-form/context/claim-bond-updater.tsx b/features/claim-bond/claim-bond-form/context/claim-bond-updater.tsx new file mode 100644 index 000000000..792f8a737 --- /dev/null +++ b/features/claim-bond/claim-bond-form/context/claim-bond-updater.tsx @@ -0,0 +1,46 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { FC, useEffect } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { CLAIM_OPTION, ClaimBondFormInputType } from './types'; +import { useClaimBondFormData } from './claim-bond-data-provider'; + +export const ClaimBondUpdater: FC = () => { + const [token, claimOption, unlockedClaimTokens] = useWatch< + ClaimBondFormInputType, + ['token', 'claimOption', 'unlockedClaimTokens'] + >({ name: ['token', 'claimOption', 'unlockedClaimTokens'] }); + + const { trigger, setValue } = useFormContext(); + const { isContract, bond, rewards, availableOptions } = + useClaimBondFormData(); + + useEffect(() => { + void trigger('amount'); + // trigger is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [token, claimOption]); + + useEffect(() => { + if (!unlockedClaimTokens && isContract) { + setValue('token', TOKENS.wsteth, { + shouldTouch: true, + shouldValidate: true, + }); + } + // setValue is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [unlockedClaimTokens]); + + useEffect(() => { + if (!bond || !rewards || !availableOptions) return; + if (availableOptions.includes(claimOption)) return; + setValue('claimOption', availableOptions[0] ?? CLAIM_OPTION.BOND_TO_RA, { + shouldTouch: true, + shouldValidate: true, + }); + // setValue is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [bond, rewards, claimOption]); + + return null; +}; diff --git a/features/claim-bond/claim-bond-form/context/index.ts b/features/claim-bond/claim-bond-form/context/index.ts index f30d92f75..de8862974 100644 --- a/features/claim-bond/claim-bond-form/context/index.ts +++ b/features/claim-bond/claim-bond-form/context/index.ts @@ -1,2 +1,4 @@ export * from './claim-bond-form-provider'; +export * from './claim-bond-data-provider'; export * from './types'; +export * from './use-claim-bond-flow'; diff --git a/features/claim-bond/claim-bond-form/context/types.ts b/features/claim-bond/claim-bond-form/context/types.ts index 4ffa67ec1..5fff01ab8 100644 --- a/features/claim-bond/claim-bond-form/context/types.ts +++ b/features/claim-bond/claim-bond-form/context/types.ts @@ -1,30 +1,57 @@ -import { type TOKENS } from 'consts/tokens'; -import { BigNumber } from 'ethers'; import { BondBalance, - LoadingRecord, + FeeSplit, NodeOperatorId, - RewardsBalance, -} from 'types'; -import { MaxValues } from './use-max-values'; + PerToken, + Rewards, + StethPoolData, + TOKENS, +} from '@lidofinance/lido-csm-sdk'; + +export type MaxValues = PerToken<[bigint, bigint]>; + +export const CLAIM_OPTION = { + /** Claim available bond (excess) + rewards → Rewards Address. */ + ALL_TO_RA: 'all-to-ra', + /** Claim only Excess Bond → Rewards Address. Requires excess bond > 0. */ + BOND_TO_RA: 'bond-to-ra', + /** Move rewards to the bond. */ + REWARDS_TO_BOND: 'rewards-to-bond', +} as const; + +export type CLAIM_OPTION = (typeof CLAIM_OPTION)[keyof typeof CLAIM_OPTION]; export type ClaimBondFormInputType = { token: TOKENS; - amount?: BigNumber; - claimRewards: boolean; - unlockClaimTokens: boolean; + amount?: bigint; + claimOption: CLAIM_OPTION; + unlockedClaimTokens: boolean; +}; + +export type ClaimBondCalculation = { + claimableBond: bigint; + claimableBondAndRewards: bigint; + claimableMaxValues: MaxValues; + // forKeys-only deficit. Drives "Insufficient bond" wording in UI labels and + // mirrors `bond.isInsufficient` shown by sources-info. + keysInsufficient: bigint; + // forKeys + locked + debt deficit. Used to size how much of the rewards is + // absorbed by bond before excess flows to the Rewards Address. + realInsufficient: bigint; + realExcess: bigint; + rewardsRemainder: bigint; + totalShare: bigint; }; export type ClaimBondFormNetworkData = { - nodeOperatorId?: NodeOperatorId; - bond?: BondBalance; - rewards?: RewardsBalance; - maxValues?: MaxValues; - rewardsAddress?: string; - isContract?: boolean; - isSplitter?: boolean; - isPaused?: boolean; - loading: LoadingRecord< - 'bond' | 'rewards' | 'maxValues' | 'info' | 'contract' | 'status' - >; + nodeOperatorId: NodeOperatorId; + bond: BondBalance; + rewards: Rewards; + poolData: StethPoolData; + rewardsAddress: string; + isContract: boolean; + isPaused: boolean; + availableOptions: CLAIM_OPTION[]; + feeSplits: FeeSplit[]; + calculation: ClaimBondCalculation; }; diff --git a/features/claim-bond/claim-bond-form/context/use-claim-bond-default-values.ts b/features/claim-bond/claim-bond-form/context/use-claim-bond-default-values.ts new file mode 100644 index 000000000..7f1493cc6 --- /dev/null +++ b/features/claim-bond/claim-bond-form/context/use-claim-bond-default-values.ts @@ -0,0 +1,17 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { useFormDefaultValues } from 'shared/hook-form/form-controller'; +import { + CLAIM_OPTION, + ClaimBondFormInputType, + ClaimBondFormNetworkData, +} from './types'; + +export const useClaimBondDefaultValues = () => { + return useFormDefaultValues( + (data) => ({ + token: data.isContract ? TOKENS.wsteth : TOKENS.steth, + claimOption: data.availableOptions[0] || CLAIM_OPTION.BOND_TO_RA, + unlockedClaimTokens: false, + }), + ); +}; diff --git a/features/claim-bond/claim-bond-form/context/use-claim-bond-flow.ts b/features/claim-bond/claim-bond-form/context/use-claim-bond-flow.ts new file mode 100644 index 000000000..8e3044037 --- /dev/null +++ b/features/claim-bond/claim-bond-form/context/use-claim-bond-flow.ts @@ -0,0 +1,88 @@ +import { type MethodAccess } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useCanPerform } from 'shared/hooks'; +import { useTxModalStagesClaimBond } from '../hooks/use-tx-modal-stages-claim-bond'; +import { useClaimBondFormData } from './claim-bond-data-provider'; +import { + CLAIM_OPTION, + ClaimBondFormInputType, + ClaimBondFormNetworkData, +} from './types'; +import { useWatch } from 'react-hook-form'; + +export type ClaimBondFlow = + | { action: 'no-access'; access: MethodAccess } + | { action: 'nothing' } + | ({ + action: 'claim'; + includeRewards: boolean; + showAmount: boolean; + maxValueIndex: 0 | 1; + } & Executable); + +export const useClaimBondFlowResolver = (): FlowResolver< + ClaimBondFormInputType, + ClaimBondFormNetworkData, + ClaimBondFlow +> => { + const { bond: bondSDK } = useSmSDK(); + const [canClaim, claimAccess] = useCanPerform(bondSDK, 'claimBond'); + const buildCallback = useTxModalStagesClaimBond(); + + return useCallback( + (input, data) => { + if (!canClaim) return { action: 'no-access', access: claimAccess }; + + if (!data || data.availableOptions.length === 0) { + return { action: 'nothing' }; + } + + const includeRewards = input.claimOption !== CLAIM_OPTION.BOND_TO_RA; + // Hide amount/token inputs when nothing is receivable on Rewards Address — + // covers both rewards fully covering an insufficient bond and splitters + // taking 100% with no excess bond. + const maxAvailableSteth = includeRewards + ? data.calculation.claimableBondAndRewards + : data.calculation.claimableBond; + const showAmount = + input.claimOption !== CLAIM_OPTION.REWARDS_TO_BOND && + maxAvailableSteth > 0n; + const amount = showAmount ? (input.amount ?? 0n) : 0n; + const maxValueIndex = + input.claimOption === CLAIM_OPTION.BOND_TO_RA ? 0 : 1; + + return { + action: 'claim', + includeRewards, + showAmount, + maxValueIndex, + submit: () => + bondSDK.claimBond({ + nodeOperatorId: data.nodeOperatorId, + token: input.token, + amount, + proof: includeRewards ? data.rewards?.proof : undefined, + shares: includeRewards ? data.rewards?.shares : undefined, + callback: buildCallback(input, data), + }), + }; + }, + [bondSDK, canClaim, claimAccess, buildCallback], + ); +}; + +export const useClaimBondFlow = (): ClaimBondFlow => { + const resolve = useClaimBondFlowResolver(); + const data = useClaimBondFormData(true); + const [token, claimOption, amount, unlockedClaimTokens] = useWatch< + ClaimBondFormInputType, + ['token', 'claimOption', 'amount', 'unlockedClaimTokens'] + >({ name: ['token', 'claimOption', 'amount', 'unlockedClaimTokens'] }); + + return resolve({ token, claimOption, amount, unlockedClaimTokens }, data); +}; diff --git a/features/claim-bond/claim-bond-form/context/use-claim-bond-form-network-data.tsx b/features/claim-bond/claim-bond-form/context/use-claim-bond-form-network-data.tsx deleted file mode 100644 index 82daf9472..000000000 --- a/features/claim-bond/claim-bond-form/context/use-claim-bond-form-network-data.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { useCallback, useMemo } from 'react'; -import { - useCsmPaused, - useIsContract, - useNodeOperatorBalance, - useNodeOperatorInfo, - useNodeOperatorRewards, -} from 'shared/hooks'; -import { type ClaimBondFormNetworkData } from './types'; -import { useMaxValues } from './use-max-values'; - -export const useClaimBondFormNetworkData = (): [ - ClaimBondFormNetworkData, - () => Promise, -] => { - const nodeOperatorId = useNodeOperatorId(); - - const { - data: bond, - update: updateBond, - initialLoading: isBondLoading, - } = useNodeOperatorBalance(nodeOperatorId); - - const { - data: rewards, - update: updateRewards, - initialLoading: isRewardsLoading, - } = useNodeOperatorRewards(nodeOperatorId); - - const { data: maxValues, initialLoading: isMaxValuesLoading } = useMaxValues({ - bond, - rewards, - }); - - const { data: nodeOperator, initialLoading: isInfoLoading } = - useNodeOperatorInfo(nodeOperatorId); - - const rewardsAddress = nodeOperator?.rewardAddress; - - const { - isContract, - isSplitter, - isLoading: isContractLoading, - } = useIsContract(rewardsAddress); - - const { data: status, initialLoading: isStatusLoading } = useCsmPaused(); - - const revalidate = useCallback(async () => { - await Promise.allSettled([updateBond(), updateRewards()]); - }, [updateBond, updateRewards]); - - const loading = useMemo( - () => ({ - isBondLoading, - isRewardsLoading, - isMaxValuesLoading, - isInfoLoading, - isContractLoading, - isStatusLoading, - }), - [ - isBondLoading, - isContractLoading, - isInfoLoading, - isMaxValuesLoading, - isRewardsLoading, - isStatusLoading, - ], - ); - - return [ - { - nodeOperatorId, - bond, - rewards, - maxValues, - rewardsAddress, - isContract, - isSplitter, - isPaused: status?.isAccountingPaused, - loading, - }, - revalidate, - ]; -}; diff --git a/features/claim-bond/claim-bond-form/context/use-claim-bond-submit.ts b/features/claim-bond/claim-bond-form/context/use-claim-bond-submit.ts deleted file mode 100644 index d234a54b1..000000000 --- a/features/claim-bond/claim-bond-form/context/use-claim-bond-submit.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { BigNumber } from 'ethers'; -import { useCallback } from 'react'; -import invariant from 'tiny-invariant'; - -import { Zero } from '@ethersproject/constants'; -import { TOKENS } from 'consts/tokens'; -import { - useCSAccountingRPC, - useCSAccountingWeb3, - useCSModuleWeb3, - useSendTx, -} from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import { NodeOperatorId, RewardProof } from 'types'; -import { runWithTransactionLogger } from 'utils'; -import { ClaimBondFormInputType, ClaimBondFormNetworkData } from '../context'; -import { useTxModalStagesClaimBond } from '../hooks/use-tx-modal-stages-claim-bond'; - -type UseClaimBondOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type ClaimBondMethodParams = { - nodeOperatorId: NodeOperatorId; - amount: BigNumber; - rewards: RewardProof; -}; - -// encapsulates eth/steth/wsteth flows -const useClaimBondTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - const CSAccountingWeb3 = useCSAccountingWeb3(); - - return useCallback( - async (token: TOKENS, params: ClaimBondMethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - invariant(CSAccountingWeb3, 'must have CSAccountingWeb3'); - - if (params.amount.isZero()) - return { - tx: await CSAccountingWeb3.populateTransaction.pullFeeRewards( - params.nodeOperatorId, - params.rewards.shares, - params.rewards.proof, - ), - txName: 'pullFeeRewards', - }; - switch (token) { - case TOKENS.ETH: - return { - tx: await CSModuleWeb3.populateTransaction.claimRewardsUnstETH( - params.nodeOperatorId, - params.amount, - params.rewards.shares, - params.rewards.proof, - ), - txName: 'claimRewardsUnstETH', - }; - case TOKENS.STETH: - return { - tx: await CSModuleWeb3.populateTransaction.claimRewardsStETH( - params.nodeOperatorId, - params.amount, - params.rewards.shares, - params.rewards.proof, - ), - txName: 'claimRewardsStETH', - }; - case TOKENS.WSTETH: - return { - tx: await CSModuleWeb3.populateTransaction.claimRewardsWstETH( - params.nodeOperatorId, - params.amount, - params.rewards.shares, - params.rewards.proof, - ), - txName: 'claimRewardsWstETH', - }; - } - }, - [CSAccountingWeb3, CSModuleWeb3], - ); -}; - -export const useClaimBondSubmit = ({ - onConfirm, - onRetry, -}: UseClaimBondOptions) => { - const { txModalStages } = useTxModalStagesClaimBond(); - const CSAccounting = useCSAccountingRPC(); - - const getTx = useClaimBondTx(); - const sendTx = useSendTx(); - - const claimBond = useCallback( - async ( - { amount = Zero, token, claimRewards }: ClaimBondFormInputType, - { nodeOperatorId, rewards }: ClaimBondFormNetworkData, - ): Promise => { - invariant(token, 'Token is not defined'); - invariant(nodeOperatorId, 'NodeOperatorId is not defined'); - - try { - txModalStages.sign({ amount, token }); - - const tx = await getTx(token, { - nodeOperatorId, - amount, - rewards: (claimRewards && rewards) || { shares: Zero, proof: [] }, - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'ClaimBond signing', - () => sendTx(tx), - ); - - txModalStages.pending({ amount, token }, txHash); - - await runWithTransactionLogger('ClaimBond block confirmation', waitTx); - - await onConfirm?.(); - - // TODO: move to onConfirm - const { current } = await CSAccounting.getBondSummary(nodeOperatorId); - - txModalStages.success({ balance: current, amount, token }, txHash); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [getTx, txModalStages, onConfirm, CSAccounting, sendTx, onRetry], - ); - - return { - claimBond, - }; -}; diff --git a/features/claim-bond/claim-bond-form/context/use-claim-bond-validation.ts b/features/claim-bond/claim-bond-form/context/use-claim-bond-validation.ts index 2ba5374b6..1ae9b802a 100644 --- a/features/claim-bond/claim-bond-form/context/use-claim-bond-validation.ts +++ b/features/claim-bond/claim-bond-form/context/use-claim-bond-validation.ts @@ -1,53 +1,62 @@ -import { formatEther } from '@ethersproject/units'; -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; import { - handleResolverValidationError, - validateBignumberMax, + useFormValidation, + validateBigintMax, validateEtherAmount, } from 'shared/hook-form/validation'; -import { useAwaitNetworkData } from 'shared/hooks'; import { getTokenDisplayName } from 'utils'; -import type { ClaimBondFormInputType, ClaimBondFormNetworkData } from './types'; +import { formatEther } from 'viem'; +import { + CLAIM_OPTION, + type ClaimBondFormInputType, + type ClaimBondFormNetworkData, +} from './types'; + +export const useClaimBondValidation = () => { + return useFormValidation( + 'token', + async ( + { token, amount, claimOption }, + { + rewards, + calculation: { + claimableBond, + claimableBondAndRewards, + claimableMaxValues, + }, + }, + validate, + ) => { + if (claimOption === CLAIM_OPTION.REWARDS_TO_BOND) return; -export const useClaimBondValidation = ( - networkData: ClaimBondFormNetworkData, -) => { - const contextPromise = useAwaitNetworkData(networkData); - return useCallback>( - async (values, _, options) => { - try { - const { token, amount, claimRewards } = values; - const { maxValues, rewards } = await contextPromise; + const includesRewards = claimOption !== CLAIM_OPTION.BOND_TO_RA; + // Mirror flow.showAmount: skip amount validation when nothing is + // receivable on the Rewards Address (e.g. splitters take 100% with no + // excess bond, or rewards fully cover an insufficient bond). + const maxAvailableSteth = includesRewards + ? claimableBondAndRewards + : claimableBond; + if (maxAvailableSteth === 0n) return; - if (options.names?.includes('amount')) { - validateEtherAmount( + await validate('amount', () => { + validateEtherAmount( + 'amount', + amount, + token, + Boolean(includesRewards && rewards?.available), + ); + + const index = claimOption === CLAIM_OPTION.BOND_TO_RA ? 0 : 1; + const maxAmount = claimableMaxValues?.[token][index]; + if (amount && maxAmount) + validateBigintMax( 'amount', amount, - token, - claimRewards && rewards?.available.gt(0), - ); - - const maxAmount = maxValues?.[token][Number(claimRewards)]; - if (amount && maxAmount) - validateBignumberMax( - 'amount', - amount, + maxAmount, + `Entered ${getTokenDisplayName(token)} amount exceeds available to claim of ${formatEther( maxAmount, - `Entered ${getTokenDisplayName(token)} amount exceeds available to claim of ${formatEther( - maxAmount, - )}`, - ); - } - - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError(error, 'ClaimBondForm', 'token'); - } + )}`, + ); + }); }, - [contextPromise], ); }; diff --git a/features/claim-bond/claim-bond-form/context/use-form-revalidate.ts b/features/claim-bond/claim-bond-form/context/use-form-revalidate.ts deleted file mode 100644 index 1bcfad032..000000000 --- a/features/claim-bond/claim-bond-form/context/use-form-revalidate.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { UseFormReturn } from 'react-hook-form'; -import { ClaimBondFormInputType } from './types'; -import { useEffect } from 'react'; -import { TOKENS } from 'consts/tokens'; - -export const useFormRevalidate = ({ - watch, - trigger, - setValue, -}: UseFormReturn) => { - const [token, claimRewards, unlockClaimTokens] = watch([ - 'token', - 'claimRewards', - 'unlockClaimTokens', - ]); - - useEffect(() => { - void trigger('amount'); - }, [token, claimRewards, trigger]); - - useEffect(() => { - if (!unlockClaimTokens) { - setValue('token', TOKENS.WSTETH, { - shouldTouch: true, - shouldValidate: true, - }); - } - }, [setValue, unlockClaimTokens]); -}; diff --git a/features/claim-bond/claim-bond-form/context/use-get-default-values.ts b/features/claim-bond/claim-bond-form/context/use-get-default-values.ts deleted file mode 100644 index cfd196f9e..000000000 --- a/features/claim-bond/claim-bond-form/context/use-get-default-values.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { TOKENS } from 'consts/tokens'; -import { useMemo } from 'react'; -import { useDefaultValues } from 'shared/hooks'; -import { ClaimBondFormInputType, ClaimBondFormNetworkData } from './types'; - -export const useGetDefaultValues = ({ - rewards, - isSplitter, - isContract, - loading, -}: ClaimBondFormNetworkData) => { - return useDefaultValues( - useMemo(() => { - if (Object.values(loading).some(Boolean)) { - return undefined; - } - - return { - token: isContract ? TOKENS.WSTETH : TOKENS.STETH, - claimRewards: rewards?.available.gt(0) ?? false, - unlockClaimTokens: !isSplitter, - }; - }, [isContract, isSplitter, loading, rewards?.available]), - ); -}; diff --git a/features/claim-bond/claim-bond-form/context/use-max-values.ts b/features/claim-bond/claim-bond-form/context/use-max-values.ts deleted file mode 100644 index 82e1ea7c8..000000000 --- a/features/claim-bond/claim-bond-form/context/use-max-values.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { MAX_ETH_AMOUNT, TOKENS } from 'consts/tokens'; -import { BigNumber } from 'ethers'; -import { - useAvailableToClaim, - useMergeSwr, - useWstethBySteth, -} from 'shared/hooks'; -import { BondBalance, RewardsBalance } from 'types'; - -const limitMaxEth = (values: BigNumber[]) => - values.map((value) => (value.gt(MAX_ETH_AMOUNT) ? MAX_ETH_AMOUNT : value)); - -type Props = { - bond?: BondBalance; - rewards?: RewardsBalance; - lockedBond?: BigNumber; -}; - -export type MaxValues = Record< - TOKENS, - [BigNumber | undefined, BigNumber | undefined] ->; - -export const useMaxValues = ({ bond, rewards }: Props) => { - const maxBond = useAvailableToClaim({ - bond, - rewards: undefined, - }); - const maxBondAndRewards = useAvailableToClaim({ - bond, - rewards, - }); - - const bondSwr = useWstethBySteth(maxBond); - const bondAndRewardsSwr = useWstethBySteth(maxBondAndRewards); - - return useMergeSwr([bondSwr, bondAndRewardsSwr], { - [TOKENS.ETH]: limitMaxEth([maxBond, maxBondAndRewards]), - [TOKENS.STETH]: [maxBond, maxBondAndRewards], - [TOKENS.WSTETH]: [bondSwr.data, bondAndRewardsSwr.data], - } as MaxValues); -}; diff --git a/features/claim-bond/claim-bond-form/controls/amount-input.tsx b/features/claim-bond/claim-bond-form/controls/amount-input.tsx index ebdc3d381..71323073b 100644 --- a/features/claim-bond/claim-bond-form/controls/amount-input.tsx +++ b/features/claim-bond/claim-bond-form/controls/amount-input.tsx @@ -1,22 +1,51 @@ -import { TOKENS } from 'consts/tokens'; +import { STETH_ROUNDING_THRESHOLD, TOKENS } from '@lidofinance/lido-csm-sdk'; import { useWatch } from 'react-hook-form'; import { FormTitle, Note } from 'shared/components'; import { FormatToken } from 'shared/formatters'; import { TokenAmountInputHookForm } from 'shared/hook-form/controls'; -import { ClaimBondFormInputType, useClaimBondFormData } from '../context'; -import { useInsufficientBondCoverAmount } from '../hooks/use-insufficient-bond-cover-amount'; +import { bigMax } from 'utils'; +import { + CLAIM_OPTION, + ClaimBondFormInputType, + useClaimBondFlow, + useClaimBondFormData, +} from '../context'; +import { computeClaimBreakdown } from '../hooks/use-claim-breakdown'; export const AmountInput: React.FC = () => { - const [token, claimRewards] = useWatch< + const [token, claimOption] = useWatch< ClaimBondFormInputType, - ['token', 'claimRewards'] - >({ name: ['token', 'claimRewards'] }); - const { maxValues } = useClaimBondFormData(); - const maxAmount = maxValues?.[token][Number(claimRewards)]; + ['token', 'claimOption'] + >({ name: ['token', 'claimOption'] }); + const flow = useClaimBondFlow(); + const data = useClaimBondFormData(true); + const { + bond, + calculation: { + realExcess, + realInsufficient, + claimableBondAndRewards, + claimableMaxValues, + }, + } = data; - const coverInsufficientAmount = useInsufficientBondCoverAmount(); + // amount-independent fields only — pass 0n to skip toRA/bondDelta computation. + const { coverAmount } = computeClaimBreakdown( + { token, amount: 0n, claimOption }, + data, + ); + const forKeysLockedDeficit = bigMax( + 0n, + bond.required + bond.locked - bond.current, + ); + const showExcessNote = + realExcess === 0n && + realInsufficient === 0n && + claimOption === CLAIM_OPTION.ALL_TO_RA; + + if (flow.action !== 'claim' || !flow.showAmount) return null; + const maxAmount = claimableMaxValues?.[token][flow.maxValueIndex]; - // TODO: reset amount on token switch, on disabled return ( <> Enter token amount @@ -24,12 +53,28 @@ export const AmountInput: React.FC = () => { fieldName="amount" token={token} maxValue={maxAmount} - disabled={maxAmount?.eq(0)} + disabled={!maxAmount} /> - {coverInsufficientAmount && ( + {coverAmount > STETH_ROUNDING_THRESHOLD && ( + + of Rewards + will compensate for the Insufficient Bond ( + ) + {claimableBondAndRewards > 0n && ( + <> +
+ {' '} + is available to claim to Rewards Address + + )} +
+ )} + {showExcessNote && ( - {' '} - of Rewards will compensate for the Insufficient bond + Any unclaimed rewards will be automatically added to your Excess Bond )} diff --git a/features/claim-bond/claim-bond-form/controls/empty-state.tsx b/features/claim-bond/claim-bond-form/controls/empty-state.tsx new file mode 100644 index 000000000..aff681f92 --- /dev/null +++ b/features/claim-bond/claim-bond-form/controls/empty-state.tsx @@ -0,0 +1,30 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import styled from 'styled-components'; + +import { ReactComponent as RewardsIcon } from 'assets/balance/empty.svg'; + +export const EmptyState: FC = () => ( + + + + Nothing to claim at the moment + + + Once rewards and excess bond increase, +
+ you'll be able to claim them there +
+
+); + +const Wrapper = styled(Stack)` + padding: ${({ theme }) => theme.spaceMap.xxl}px 0; + text-align: center; + + svg { + color: var(--lido-color-textSecondary); + opacity: 0.8; + } +`; diff --git a/features/claim-bond/claim-bond-form/controls/source-select.tsx b/features/claim-bond/claim-bond-form/controls/source-select.tsx index 63357616c..4507ef670 100644 --- a/features/claim-bond/claim-bond-form/controls/source-select.tsx +++ b/features/claim-bond/claim-bond-form/controls/source-select.tsx @@ -1,95 +1,98 @@ -import { Checkbox } from '@lidofinance/lido-ui'; -import { BOND_EXCESS, BOND_INSUFFICIENT } from 'consts/text'; -import { TOKENS } from 'consts/tokens'; -import { FC, useEffect } from 'react'; -import { useController, useFormContext } from 'react-hook-form'; +import { FC } from 'react'; +import { useController } from 'react-hook-form'; import { - AmountWithPrice, + Address, FormTitle, - Latice, + IconTooltip, + RadioButton, + RadioIcon, + SquaredChip, Stack, - TitledSelectableAmount, } from 'shared/components'; +import { Text } from '@lidofinance/lido-ui'; import { ClaimBondFormInputType, useClaimBondFormData } from '../context'; +import { useClaimOptions } from '../hooks/use-claim-options'; +import { FeeSplit } from '@lidofinance/lido-csm-sdk'; export const SourceSelect: FC = () => { - const { bond, rewards, loading, maxValues } = useClaimBondFormData(); - - const { field } = useController({ - name: 'claimRewards', - disabled: bond?.isInsufficient, + const { options } = useClaimOptions(); + const { field } = useController({ + name: 'claimOption', }); - const { setValue } = useFormContext(); + return ( + <> + }>Select claiming option + + {options.map(({ option, label, description, disabled }) => ( + field.onChange(option)} + > + + + + + + {label} + + + + {description} + + + + + ))} + + + ); +}; - const availableToClaim = maxValues?.[TOKENS.STETH][Number(field.value)]; +const formatShare = (share: bigint) => `${Number(share) / 100}%`; - useEffect(() => { - if (bond?.isInsufficient) { - setValue('claimRewards', true); - } - }, [bond?.isInsufficient, setValue]); +const SplittersChip: FC = () => { + const { feeSplits } = useClaimBondFormData(true); - const showLockedBond = bond?.locked.gt(0); + if (feeSplits.length === 0) return null; return ( - <> - - Available to claim - - - - - } - help="The rewards amount available to claim, obtained from all active validators of the Node Operator" - loading={loading.isRewardsLoading} - amount={rewards?.available} - token={TOKENS.STETH} - /> - - } - help={ - bond?.isInsufficient - ? 'Insufficient bond is the missing amount of stETH required to cover all operator’s keys. In case of a bond insufficient, "unbonded" validators are requested for exit by the protocol' - : 'The bond amount available to claim without having to exit validators' - } - sign={bond?.isInsufficient ? 'minus' : 'plus'} - loading={loading.isBondLoading} - amount={bond?.delta} - token={TOKENS.STETH} - /> - {showLockedBond && ( - } - help="Bond may be locked in the case of an MEV stealing event reported by a dedicated committee. This measure ensures that Node Operators are held accountable for any misbehavior or rule violations." - loading={loading.isBondLoading} - amount={bond?.locked} - token={TOKENS.ETH} - sign="minus" - /> - )} - - + + SPLITTERS ON{' '} + } + /> + ); }; + +const SplittersTooltip: FC<{ feeSplits: FeeSplit[] }> = ({ feeSplits }) => ( + + + When you claim rewards, they will be distributed according to the + proportions below + + + {feeSplits.map((split) => ( + +
+ {formatShare(split.share)} + + ))} + + +); diff --git a/features/claim-bond/claim-bond-form/controls/sources-info.tsx b/features/claim-bond/claim-bond-form/controls/sources-info.tsx new file mode 100644 index 000000000..25790f9d5 --- /dev/null +++ b/features/claim-bond/claim-bond-form/controls/sources-info.tsx @@ -0,0 +1,192 @@ +import { PERCENT_BASIS, TOKENS } from '@lidofinance/lido-csm-sdk'; +import { Divider, Text } from '@lidofinance/lido-ui'; +import { BOND_EXCESS, BOND_INSUFFICIENT } from 'consts/text'; +import { getNextDistribution, useFrameInfo } from 'modules/web3'; +import { FC, Fragment, ReactNode } from 'react'; +import { useFormState } from 'react-hook-form'; +import { Block, Grid, IconTooltip, Stack } from 'shared/components'; +import { FormatToken } from 'shared/formatters'; +import { useShowRule } from 'shared/hooks'; +import styled from 'styled-components'; +import { useClaimBondFormData } from '../context'; + +import { ReactComponent as BondIcon } from 'assets/balance/bond.svg'; +import { ReactComponent as RewardsIcon } from 'assets/balance/rewards.svg'; +import { moduleMeta } from 'consts'; +import { Balance } from 'features/dashboard/bond/balance'; + +const LOCKED_TOOLTIP_CSM = + 'Penalties have been applied to your Node Operator because of an MEV stealing event reported by a dedicated committee. If it is not covered, the corresponding amount of your bond may be burned. See details in the Locked Bond tab.'; + +const LOCKED_TOOLTIP_CM = + 'Penalties have been applied to your Node Operator. If they are not covered, the corresponding amount of your bond may be burned. See details in the Locked Bond tab.'; + +const NEGATIVE_FIELDS = ['pendingToSplit', 'debt', 'locked'] as const; + +type BondNegativeProps = { + title: ReactNode; + tooltip?: ReactNode; + amount: bigint; + token: TOKENS; + 'data-testid'?: string; +}; + +const useBondNegativeMetadata = () => { + const check = useShowRule(); + + return { + locked: { + title: 'Locked:', + tooltip: check('IS_CSM') ? LOCKED_TOOLTIP_CSM : LOCKED_TOOLTIP_CM, + token: TOKENS.steth, + }, + pendingToSplit: { + title: 'Splitter debt:', + tooltip: `Is the amount that has not been split due to insufficient bond or locked bond that occurred earlier. When claiming rewards ${moduleMeta.shortName} will try to split this amount from excess bond.`, + token: TOKENS.steth, + }, + debt: { + title: 'Debt:', + tooltip: + 'Outstanding penalty that exceeded your bond balance. Top up your bond to clear it.', + token: TOKENS.steth, + }, + } as Record< + (typeof NEGATIVE_FIELDS)[number], + Pick + >; +}; + +export const SourcesInfo: FC = () => { + const { isLoading } = useFormState(); + const { bond, rewards, calculation } = useClaimBondFormData(); + const { data: nextDistribution } = useFrameInfo(getNextDistribution); + const bondNegativeMetadata = useBondNegativeMetadata(); + + const negative = bond ? NEGATIVE_FIELDS.filter((field) => bond[field]) : []; + + const splittable = + ((rewards?.available ?? 0n) * (calculation?.totalShare ?? 0n)) / + PERCENT_BASIS; + + if (isLoading || !bond || !rewards) { + return null; + } + + return ( + + + + + Rewards balance + + + } + amount={rewards.available} + approx + /> + + + + + + {splittable > 0n && ( + + + + )} + + + + + {bond.isInsufficient ? BOND_INSUFFICIENT : BOND_EXCESS} + 0n + ? 'Locked bond has not been burned yet but cannot be claimed, so it is not displayed as part of your Excess Bond' + : 'The bond amount available to claim without having to exit validators. Increases daily.' + } + /> + + } + amount={bond.isInsufficient ? -bond.delta : bond.delta} + warning={bond.isInsufficient} + approx + /> + + + + + + + {negative.length > 0 && ( + + {negative.map((field, index) => ( + + {index > 0 && } + + + ))} + + )} + + + ); +}; + +const BondNegative: FC = ({ + title, + tooltip, + amount, + token, + 'data-testid': testId, +}) => ( + + + {title} + + + + + + +); + +const ContentPadding = styled(Stack)` + padding: ${({ theme }) => theme.spaceMap.md}px + ${({ theme }) => theme.spaceMap.xxl}px; +`; + +const FooterStyle = styled.div` + background: var(--lido-color-border); + margin-top: -${({ theme }) => theme.spaceMap.xs}px; + padding: ${({ theme }) => theme.spaceMap.sm}px + ${({ theme }) => theme.spaceMap.xxl}px; + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spaceMap.sm}px; +`; + +const IconWrapper = styled.div` + display: flex; + flex: 0 0 auto; +`; diff --git a/features/claim-bond/claim-bond-form/controls/submit-button.tsx b/features/claim-bond/claim-bond-form/controls/submit-button.tsx index 82909fe42..68e0fd4bd 100644 --- a/features/claim-bond/claim-bond-form/controls/submit-button.tsx +++ b/features/claim-bond/claim-bond-form/controls/submit-button.tsx @@ -1,22 +1,14 @@ import { PausedButton, SubmitButtonHookForm } from 'shared/hook-form/controls'; -import { ClaimBondFormInputType, useClaimBondFormData } from '../context'; -import { useWatch } from 'react-hook-form'; +import { useClaimBondFormData } from '../context'; +import { useClaimOptions } from '../hooks/use-claim-options'; export const SubmitButton = () => { - const claimRewards = useWatch({ - name: 'claimRewards', - }); + const { isPaused } = useClaimBondFormData(true); + const { submitLabel } = useClaimOptions(); - const { isPaused } = useClaimBondFormData(); if (isPaused) { return ; } - // TODO: disable - // TODO: nothing to claim - return ( - - {claimRewards ? 'Claim Rewards and Bond' : 'Claim Bond'} - - ); + return {submitLabel}; }; diff --git a/features/claim-bond/claim-bond-form/controls/token-select.tsx b/features/claim-bond/claim-bond-form/controls/token-select.tsx index fa76423ea..d9a1aa05e 100644 --- a/features/claim-bond/claim-bond-form/controls/token-select.tsx +++ b/features/claim-bond/claim-bond-form/controls/token-select.tsx @@ -1,11 +1,11 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; import { Checkbox } from '@lidofinance/lido-ui'; +import { INSTANT_WAITING_TIME } from 'consts'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { TOKENS } from 'consts/tokens'; import { PATH } from 'consts/urls'; import { useController, useWatch } from 'react-hook-form'; import { FormTitle, - MatomoLink, Note, Stack, TokenAmount, @@ -15,27 +15,50 @@ import { import { TokenButtonsHookForm } from 'shared/hook-form/controls'; import { LocalLink } from 'shared/navigate'; import { getTokenDisplayName } from 'utils'; -import { ClaimBondFormInputType, useClaimBondFormData } from '../context'; +import { + ClaimBondFormInputType, + useClaimBondFlow, + useClaimBondFormData, +} from '../context'; +import { useWithdrawalWaitingTime } from '../hooks/use-withdrawal-waiting-time'; export const TokenSelect: React.FC = () => { - const [token, claimRewards] = useWatch< - ClaimBondFormInputType, - ['token', 'claimRewards'] - >({ name: ['token', 'claimRewards'] }); - const { loading, maxValues, isContract, isSplitter } = useClaimBondFormData(); - const isLoading = loading.isBondLoading || loading.isRewardsLoading; + const [token] = useWatch({ + name: ['token'], + }); + const { + isContract, + feeSplits, + calculation: { claimableMaxValues }, + } = useClaimBondFormData(true); + const flow = useClaimBondFlow(); + + const maxEthAmount = claimableMaxValues?.[TOKENS.eth]?.[1]; + const { + data: { text: waitingTimeValue } = {}, + isPending: isWaitingTimeLoading, + } = useWithdrawalWaitingTime(maxEthAmount); const { field: unlockField } = useController< ClaimBondFormInputType, - 'unlockClaimTokens' + 'unlockedClaimTokens' >({ - name: 'unlockClaimTokens', + name: 'unlockedClaimTokens', }); + if (flow.action !== 'claim' || !flow.showAmount) return null; + const maxIdx = flow.maxValueIndex; + return ( <> Choose a token to claim - {isContract && !isSplitter && ( + {flow.includeRewards && feeSplits.length > 0 && ( + + Splitter addresses receive stETH. Choose the token for your Rewards + Address. + + )} + {isContract && ( The Rewards Address of your Node Operator seems to be a smart contract. Please ensure the smart contract you use for the Reward @@ -45,57 +68,56 @@ export const TokenSelect: React.FC = () => { )} ), - [TOKENS.STETH]: ( + [TOKENS.steth]: ( ), - [TOKENS.WSTETH]: ( + [TOKENS.wsteth]: ( ), }} /> - {token === TOKENS.ETH && ( - + {token === TOKENS.eth && ( + After receiving NFT you will need to claim ETH manually. Follow{' '} FAQ @@ -103,21 +125,13 @@ export const TokenSelect: React.FC = () => { for more details. )} - {isSplitter && ( + {isContract && ( <> - The Rewards Address of your Node Operator is a splitter contract. It - is strongly recommended to claim bond and rewards in wstETH only. - ETH withdrawal NFT is not compatible with the splitter, while a - rebasing token like stETH may not receive incremental rewards. More - information can be found in the{' '} - - splits.org documentation - - . + The Rewards Address of your Node Operator seems to be a smart + contract. Please ensure the smart contract you use for the Reward + Address is compatible with the chosen token for claiming of your + bond/rewards. { + const { + coverAmount, + splittable, + toRA, + toRAToken, + token, + bondDelta, + debtBurned, + debtRemain, + includesRewards, + hasSplits, + isRewardsToBond, + } = breakdown; + + // Source label: "bond" when no rewards pulled, "rewards" when only rewards + // are being delivered to RA, "bond and rewards" when both flow to RA. + // bondDelta < 0 means existing excess bond is being claimed alongside rewards. + const sourceText = !includesRewards + ? 'bond' + : isRewardsToBond + ? 'rewards' + : bondDelta < 0n + ? 'bond and rewards' + : 'rewards'; + const operationText = + token === TOKENS.eth ? 'requesting withdrawal of' : 'claiming'; + + const Component = isPending ? TxStagePending : TxStageSign; + + const hasPrimary = + (hasSplits && splittable > 0n) || toRA > 0n || bondDelta !== 0n; + const hasSecondary = + (includesRewards && coverAmount > STETH_ROUNDING_THRESHOLD) || + (includesRewards && debtBurned > 0n) || + debtRemain > 0n; + + return ( + + You are {operationText} {sourceText} + + } + description={ + + {hasSplits && splittable > 0n && ( + } + /> + )} + {toRA > 0n && ( + + Rewards Address + +
} + /> + + + } + value={} + /> + )} + {bondDelta > 0n && ( + + + + + } + /> + )} + {bondDelta < 0n && ( + + − + + } + /> + )} + + {hasPrimary && hasSecondary && } + + {includesRewards && coverAmount > STETH_ROUNDING_THRESHOLD && ( + } + /> + )} + {includesRewards && debtBurned > 0n && ( + } + /> + )} + {debtRemain > 0n && ( + } + /> + )} + + } + /> + ); +}; + +type RowProps = { label: ReactNode; value: ReactNode; muted?: boolean }; +const Row = ({ label, value, muted }: RowProps) => ( + <> + + {value} + +); + +const Receipt = styled.div` + display: inline-grid; + grid-template-columns: minmax(0, 1fr) auto; + column-gap: ${({ theme }) => theme.spaceMap.lg}px; + row-gap: ${({ theme }) => theme.spaceMap.xs}px; + text-align: left; + margin-top: ${({ theme }) => theme.spaceMap.md}px; + max-width: 100%; + align-items: baseline; +`; + +const Label = styled.div<{ $muted?: boolean }>` + color: var( + --lido-color-${({ $muted }) => ($muted ? 'textSecondary' : 'text')} + ); + font-size: ${({ theme, $muted }) => + $muted ? theme.fontSizesMap.xxs : theme.fontSizesMap.xs}px; + line-height: 1.4; +`; + +const Value = styled.div<{ $muted?: boolean }>` + color: var( + --lido-color-${({ $muted }) => ($muted ? 'textSecondary' : 'text')} + ); + font-weight: ${({ $muted }) => ($muted ? 400 : 700)}; + font-size: ${({ theme, $muted }) => + $muted ? theme.fontSizesMap.xxs : theme.fontSizesMap.xs}px; + text-align: right; + white-space: nowrap; +`; + +const Divider = styled.div` + grid-column: 1 / -1; + border-top: 1px solid var(--lido-color-border); + margin: ${({ theme }) => theme.spaceMap.xs}px 0; +`; + +const AddressLine = styled.span` + display: block; + margin-top: 2px; +`; diff --git a/features/claim-bond/claim-bond-form/hooks/use-bond-receive-amount.ts b/features/claim-bond/claim-bond-form/hooks/use-bond-receive-amount.ts deleted file mode 100644 index abeccfd1f..000000000 --- a/features/claim-bond/claim-bond-form/hooks/use-bond-receive-amount.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Zero } from '@ethersproject/constants'; -import { useWatch } from 'react-hook-form'; -import { ClaimBondFormInputType, useClaimBondFormData } from '../context'; -import { useStethAmount } from './use-steth-amount'; - -export const useBondReceiveAmount = () => { - const [token, amount] = useWatch< - ClaimBondFormInputType, - ['token', 'amount', 'claimRewards'] - >({ - name: ['token', 'amount', 'claimRewards'], - }); - - const { rewards } = useClaimBondFormData(); - - const stethAmount = useStethAmount(token, amount ?? Zero); - const bondReceive = rewards?.available.sub(stethAmount ?? Zero) ?? Zero; - - return bondReceive.lt(0) ? Zero : bondReceive; -}; diff --git a/features/claim-bond/claim-bond-form/hooks/use-claim-breakdown.ts b/features/claim-bond/claim-bond-form/hooks/use-claim-breakdown.ts new file mode 100644 index 000000000..3b08dc583 --- /dev/null +++ b/features/claim-bond/claim-bond-form/hooks/use-claim-breakdown.ts @@ -0,0 +1,141 @@ +import { + convertEthToShares, + convertSharesToEth, + PERCENT_BASIS, + TOKENS, +} from '@lidofinance/lido-csm-sdk'; +import { useWatch } from 'react-hook-form'; +import { bigMax, bigMin } from 'utils'; +import { + CLAIM_OPTION, + ClaimBondFormInputType, + ClaimBondFormNetworkData, + useClaimBondFormData, +} from '../context'; + +export type ClaimBreakdown = { + /** stETH from incoming rewards absorbed by bond top-up to cover forKeys + locked deficit (debt cover tracked separately as `debtBurned`). */ + coverAmount: bigint; + /** Gross stETH flowing into the splitter contract (basis for per-recipient share). */ + splittableGross: bigint; + /** Total stETH paid to splitter recipients (sum across all = gross × Σshare). */ + splittable: bigint; + /** stETH that will be delivered to the Rewards Address. */ + toRA: bigint; + /** Amount the Rewards Address will receive in the operator-selected token (wstETH shares for wstETH, stETH otherwise). */ + toRAToken: bigint; + /** Token chosen by the operator for the claim payout. */ + token: TOKENS; + /** Change in Excess Bond (positive = grows, negative = shrinks). */ + bondDelta: bigint; + /** Bond debt burned during this tx. */ + debtBurned: bigint; + /** Bond debt left after this tx. */ + debtRemain: bigint; + /** Whether a rewards proof will be submitted (rewards pulled in). */ + includesRewards: boolean; + /** Whether the operator has any splitter recipients configured. */ + hasSplits: boolean; + /** Whether the user explicitly redirects rewards to bond (no RA payout). */ + isRewardsToBond: boolean; +}; + +type BreakdownInput = Pick< + ClaimBondFormInputType, + 'token' | 'amount' | 'claimOption' +>; + +// Mirrors Accounting._pullAndSplitFeeRewards (Accounting.sol:460-502): +// 1. distribute R into bond, increase pendingToSplit by R +// 2. _coverBondDebt burns min(debt, current+R) from bond +// 3. claimable = saturatingSub(current+R, required+locked+debt) +// 4. splittableGross = min(claimable, pendingToSplit+R) flows to FeeSplits +// 5. splitter pays Σshare/PERCENT_BASIS of gross to recipients; remainder +// stays in bond as additional excess +// 6. toRA = min(userClaim, claimable - splitterCut) +// SDK note: bond.required equals forKeys only; bond.locked and bond.debt are separate fields. +export const computeClaimBreakdown = ( + { token, amount, claimOption }: BreakdownInput, + data: ClaimBondFormNetworkData, +): ClaimBreakdown => { + const { + bond, + rewards, + poolData, + feeSplits, + calculation: { totalShare }, + } = data; + + const isRewardsToBond = claimOption === CLAIM_OPTION.REWARDS_TO_BOND; + const includesRewards = claimOption !== CLAIM_OPTION.BOND_TO_RA; + const hasSplits = feeSplits.length > 0; + + const distributed = includesRewards ? rewards.available : 0n; + + const claimablePre = bigMax( + 0n, + bond.current - bond.required - bond.locked - bond.debt, + ); + const claimable = bigMax( + 0n, + bond.current + distributed - bond.required - bond.locked - bond.debt, + ); + const totalAbsorbed = distributed - (claimable - claimablePre); + // _coverBondDebt only runs inside _creditBondShares, i.e. when a rewards + // proof is submitted. BOND_TO_RA passes no proof, so debt is untouched. + const debtBurned = includesRewards + ? bigMin(bond.debt, bond.current + distributed) + : 0n; + const debtRemain = bond.debt - debtBurned; + // Of `debtBurned`, the portion attributable to fresh rewards is bounded by + // `distributed`; the rest came from pre-existing bond. `coverAmount` is what + // remains of the absorbed rewards after subtracting that — i.e. the portion + // that filled forKeys + locked deficit. + const debtCoveredFromRewards = bigMin(distributed, debtBurned); + const coverAmount = bigMax(0n, totalAbsorbed - debtCoveredFromRewards); + + const splittableGross = hasSplits + ? bigMin(claimable, bond.pendingToSplit + distributed) + : 0n; + const splittable = (splittableGross * totalShare) / PERCENT_BASIS; + + const userClaimSteth = isRewardsToBond + ? 0n + : token === TOKENS.wsteth + ? convertSharesToEth(amount ?? 0n, poolData) + : (amount ?? 0n); + + const toRA = bigMin(userClaimSteth, claimable - splittable); + // The contract pays the Rewards Address in the chosen token: stETH/ETH go + // out 1:1 (ETH via withdrawal NFT), wstETH is the share-equivalent of + // `toRA`. Mirrors the conversion in `userClaimSteth`. + const toRAToken = + token === TOKENS.wsteth ? convertEthToShares(toRA, poolData) : toRA; + + const bondDelta = claimable - claimablePre - splittable - toRA; + + return { + coverAmount, + splittableGross, + splittable, + toRA, + toRAToken, + token, + bondDelta, + debtBurned, + debtRemain, + includesRewards, + hasSplits, + isRewardsToBond, + }; +}; + +export const useClaimBreakdown = (): ClaimBreakdown => { + const data = useClaimBondFormData(true); + const [token, amount, claimOption] = useWatch< + ClaimBondFormInputType, + ['token', 'amount', 'claimOption'] + >({ name: ['token', 'amount', 'claimOption'] }); + + return computeClaimBreakdown({ token, amount, claimOption }, data); +}; diff --git a/features/claim-bond/claim-bond-form/hooks/use-claim-options.tsx b/features/claim-bond/claim-bond-form/hooks/use-claim-options.tsx new file mode 100644 index 000000000..ae872f7a5 --- /dev/null +++ b/features/claim-bond/claim-bond-form/hooks/use-claim-options.tsx @@ -0,0 +1,268 @@ +import { ReactNode } from 'react'; +import { + BondBalance, + FeeSplit, + STETH_ROUNDING_THRESHOLD, + TOKENS, +} from '@lidofinance/lido-csm-sdk'; +import { useWatch } from 'react-hook-form'; +import styled, { css } from 'styled-components'; + +import { ReactComponent as _BondIcon } from 'assets/balance/bond.svg'; +import { ReactComponent as _RewardsIcon } from 'assets/balance/rewards.svg'; + +import { + CLAIM_OPTION, + ClaimBondCalculation, + ClaimBondFormInputType, + useClaimBondFormData, +} from '../context'; + +const iconStyle = css` + width: 22px; + height: 22px; + flex: 0 0 auto; + vertical-align: bottom; + padding-right: 4px; + + &:has(+ svg) { + padding-right: 0; + } +`; + +const BondIcon = styled(_BondIcon)` + ${iconStyle} +`; +const RewardsIcon = styled(_RewardsIcon)` + ${iconStyle} +`; + +type Meta = { label: ReactNode; description: ReactNode }; + +const COMPENSATE_AND_CLAIM_REWARDS: Meta = { + label: ( + <> + Rewards → Rewards Address + + ), + description: 'Compensate the Insufficient Bond and claim Rewards', +}; + +const CLAIM_ALL: Meta = { + label: ( + <> + All → Rewards Address + + ), + description: 'Claim both Excess Bond and Rewards', +}; + +const CLAIM_EXCESS_BOND: Meta = { + label: ( + <> + + Excess Bond → Rewards Address + + ), + description: 'Claim only Excess Bond. Rewards remain unclaimed.', +}; + +const CLAIM_EXCESS_BOND_WITH_PENDING_SPLIT: Meta = { + label: CLAIM_EXCESS_BOND.label, + description: + 'Claim Excess Bond. Pending splitter share will be settled from bond.', +}; + +const COMPENSATE_INSUFFICIENT: Meta = { + label: ( + <> + Rewards → Bond + + ), + description: 'Compensate the Insufficient Bond', +}; + +const REWARDS_TO_EXCESS_BOND: Meta = { + label: ( + <> + Rewards → Excess Bond + + ), + description: 'Move all rewards to the bond. Best for uploading more keys.', +}; + +const SPLIT_REWARDS_ONLY: Meta = { + label: ( + <> + Rewards → Splitter addresses + + ), + description: 'Split rewards', +}; + +const SPLIT_AND_CLAIM_BOND: Meta = { + label: ( + <> + Rewards → Splitter addresses, +
+ Excess Bond → Rewards Address + + ), + description: 'Split rewards and claim Excess bond', +}; + +const SPLIT_AND_COMPENSATE_TO_RA: Meta = { + label: ( + <> + Rewards → Splitter addresses → Rewards Address + + ), + description: 'Split rewards, send remaining to Rewards Address', +}; + +const SPLIT_REWARDS_TO_BOND: Meta = { + label: ( + <> + Rewards → Splitter addresses → Excess bond + + ), + description: 'Split rewards, send remaining to Excess bond', +}; + +type Ctx = ClaimBondCalculation & { + feeSplits: FeeSplit[]; + bond: BondBalance; +}; + +type Descriptor = Meta & { submitLabel: string }; + +const claimSubmit = (token: TOKENS) => + token === TOKENS.eth ? 'Request withdrawal' : 'Claim'; + +const rewardsToBondSubmit = (rewardsRemainder: bigint) => + rewardsRemainder === 0n ? 'Compensate' : 'Claim rewards to the Bond balance'; + +const describe = ( + option: CLAIM_OPTION, + ctx: Ctx, + token: TOKENS, +): Descriptor => { + const { keysInsufficient, realExcess, rewardsRemainder, feeSplits, bond } = + ctx; + + const hasSplits = feeSplits.length > 0; + const hasPendingToSplit = bond.pendingToSplit > 0n; + // Only forKeys-deficit triggers "Compensate Insufficient Bond" wording. + // Locked/debt absorb rewards into bond too, but the operator does not see + // "Insufficient bond" in sources-info, so the Claim variants are used and + // the breakdown panel reflects the actual on-chain effect. + const isKeysInsufficient = keysInsufficient > STETH_ROUNDING_THRESHOLD; + + switch (option) { + case CLAIM_OPTION.ALL_TO_RA: { + // "Compensate + claim Rewards" only when rewards actually survive the + // insufficient-bond top-up. Otherwise ALL_TO_RA falls through to a basic + // CLAIM_ALL ("All → Rewards Address") that conveys the option's intent + // regardless of how much actually reaches RA — keeps the label distinct + // from REWARDS_TO_BOND when the option is disabled. + if (isKeysInsufficient && rewardsRemainder > 0n) { + return { + ...(hasSplits + ? SPLIT_AND_COMPENSATE_TO_RA + : COMPENSATE_AND_CLAIM_REWARDS), + submitLabel: claimSubmit(token), + }; + } + if (hasSplits && realExcess === 0n) { + return { ...SPLIT_REWARDS_ONLY, submitLabel: claimSubmit(token) }; + } + return { + ...(hasSplits ? SPLIT_AND_CLAIM_BOND : CLAIM_ALL), + submitLabel: claimSubmit(token), + }; + } + + case CLAIM_OPTION.BOND_TO_RA: + return { + ...(hasSplits && hasPendingToSplit + ? CLAIM_EXCESS_BOND_WITH_PENDING_SPLIT + : CLAIM_EXCESS_BOND), + submitLabel: claimSubmit(token), + }; + + case CLAIM_OPTION.REWARDS_TO_BOND: { + // Rewards don't cover the insufficient bond (rewardsRemainder === 0): the + // whole amount compensates the bond, nothing is split and nothing reaches + // excess — so use the compensation copy even with splitters configured. + if (isKeysInsufficient && rewardsRemainder === 0n) { + return { + ...COMPENSATE_INSUFFICIENT, + submitLabel: rewardsToBondSubmit(rewardsRemainder), + }; + } + if (hasSplits) { + return { + ...SPLIT_REWARDS_TO_BOND, + submitLabel: rewardsToBondSubmit(rewardsRemainder), + }; + } + if (isKeysInsufficient) { + return { + ...COMPENSATE_INSUFFICIENT, + submitLabel: rewardsToBondSubmit(rewardsRemainder), + }; + } + return { + ...REWARDS_TO_EXCESS_BOND, + submitLabel: 'Claim rewards to the Bond balance', + }; + } + } +}; + +const ORDER: readonly CLAIM_OPTION[] = [ + CLAIM_OPTION.ALL_TO_RA, + CLAIM_OPTION.BOND_TO_RA, + CLAIM_OPTION.REWARDS_TO_BOND, +]; + +export type ClaimOptionView = { + option: CLAIM_OPTION; + label: ReactNode; + description: ReactNode; + disabled: boolean; +}; + +export type ClaimOptions = { + options: ClaimOptionView[]; + submitLabel: string; +}; + +export const useClaimOptions = (): ClaimOptions => { + const { bond, feeSplits, calculation, availableOptions } = + useClaimBondFormData(true); + const [token, claimOption] = useWatch< + ClaimBondFormInputType, + ['token', 'claimOption'] + >({ name: ['token', 'claimOption'] }); + + const ctx: Ctx = { + ...calculation, + feeSplits, + bond, + }; + + const options: ClaimOptionView[] = ORDER.map((option) => { + const { label, description } = describe(option, ctx, token); + return { + option, + label, + description, + disabled: availableOptions.indexOf(option) < 0, + }; + }).sort((a, b) => Number(a.disabled) - Number(b.disabled)); + + const { submitLabel } = describe(claimOption, ctx, token); + + return { options, submitLabel }; +}; diff --git a/features/claim-bond/claim-bond-form/hooks/use-insufficient-bond-cover-amount.ts b/features/claim-bond/claim-bond-form/hooks/use-insufficient-bond-cover-amount.ts deleted file mode 100644 index 6a8d0e2ea..000000000 --- a/features/claim-bond/claim-bond-form/hooks/use-insufficient-bond-cover-amount.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Zero } from '@ethersproject/constants'; -import { useClaimBondFormData } from '../context'; - -export const useInsufficientBondCoverAmount = () => { - const { bond, rewards } = useClaimBondFormData(); - - return bond?.isInsufficient - ? bond.delta.gt(rewards?.available ?? Zero) - ? rewards?.available - : bond.delta - : undefined; -}; diff --git a/features/claim-bond/claim-bond-form/hooks/use-steth-amount.ts b/features/claim-bond/claim-bond-form/hooks/use-steth-amount.ts deleted file mode 100644 index 275118a26..000000000 --- a/features/claim-bond/claim-bond-form/hooks/use-steth-amount.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { TOKENS } from 'consts/tokens'; -import { BigNumber } from 'ethers'; -import { useStethByWsteth } from 'shared/hooks'; - -export const useStethAmount = (token: TOKENS, amount?: BigNumber) => { - const { data: wstethToSteth } = useStethByWsteth( - (token === TOKENS.WSTETH && amount) || undefined, - ); - - return token === TOKENS.WSTETH ? wstethToSteth : amount; -}; diff --git a/features/claim-bond/claim-bond-form/hooks/use-tx-modal-stages-claim-bond.tsx b/features/claim-bond/claim-bond-form/hooks/use-tx-modal-stages-claim-bond.tsx index 97c2c3122..627f289c0 100644 --- a/features/claim-bond/claim-bond-form/hooks/use-tx-modal-stages-claim-bond.tsx +++ b/features/claim-bond/claim-bond-form/hooks/use-tx-modal-stages-claim-bond.tsx @@ -1,106 +1,99 @@ -import type { BigNumber } from 'ethers'; - -import { TOKENS } from 'consts/tokens'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { getExternalLinks } from 'consts/external-links'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { PATH } from 'consts/urls'; import { MatomoLink } from 'shared/components'; import { TxLinkEtherscan } from 'shared/components/tx-link-etherscan'; +import { LocalLink } from 'shared/navigate'; import { - TransactionModalTransitStage, TxAmount, - TxStageOperationSucceedBalanceShown, - TxStageSignOperationAmount, TxStageSuccess, - getGeneralTransactionModalStages, - useTransactionModalStage, + useTxStages, } from 'shared/transaction-modal'; -import { getExternalLinks } from 'consts/external-links'; -import { LocalLink } from 'shared/navigate'; -import { PATH } from 'consts/urls'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; - -const STAGE_OPERATION_ARGS = { - operationText: 'Claiming Bond', -}; - -type Props = { amount: BigNumber; token: TOKENS }; -type SuccessProps = { amount: BigNumber; balance: BigNumber; token: TOKENS }; +import { + ClaimBondFormInputType, + ClaimBondFormNetworkData, +} from '../context/types'; +import { computeClaimBreakdown } from './use-claim-breakdown'; +import { TxStageClaim } from './tx-stage-claim'; const { stakeWidget } = getExternalLinks(); -const getTxModalStagesClaimBond = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: ({ amount, token }: Props) => - transitStage( - , - ), - - pending: ({ amount, token }: Props, txHash?: string) => - transitStage( - , - ), - - success: ({ amount, balance, token }: SuccessProps, txHash?: string) => - transitStage( - token === TOKENS.ETH ? ( - // TODO: matomo events - - Request withdrawal of{' '} - has been sent. - Check{' '} - - Claim tab on the Lido Staking Widget - {' '} - to view your withdrawal requests or view your transaction on{' '} - . -
-
- Add NFT to your wallet to monitor the status of your request. - - This guide - {' '} - will help you to do this. - - } - /> - ) : ( - - ), - { - isClosableOnLedger: true, - }, - ), -}); +export const useTxModalStagesClaimBond = () => + useTxStages( + (transitStage, input, data) => { + const breakdown = computeClaimBreakdown(input, data); + const { toRA } = breakdown; -export const useTxModalStagesClaimBond = () => { - return useTransactionModalStage(getTxModalStagesClaimBond); -}; + return { + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (_result, txHash) => + transitStage( + input.token === TOKENS.eth ? ( + + Request withdrawal of{' '} + has been + sent. Check{' '} + + Claim tab on the Lido Staking Widget + {' '} + to view your withdrawal requests or view your transaction on{' '} + . +
+
+ Add NFT to your wallet to monitor the status of your + request. + + This guide + {' '} + will help you to do this. + + } + /> + ) : ( + + Transaction can be viewed on{' '} + . + + } + /> + ), + ), + }; + }, + ); diff --git a/features/claim-bond/claim-bond-form/hooks/use-withdrawal-waiting-time.ts b/features/claim-bond/claim-bond-form/hooks/use-withdrawal-waiting-time.ts new file mode 100644 index 000000000..f6d823f3c --- /dev/null +++ b/features/claim-bond/claim-bond-form/hooks/use-withdrawal-waiting-time.ts @@ -0,0 +1,45 @@ +import { LidoSDKWithdraw } from '@lidofinance/lido-ethereum-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { parseISO } from 'date-fns'; +import { useLidoSDK } from 'modules/web3'; +import { plural } from 'utils'; +import { countDaysLeft } from 'utils/format-date'; + +type WaitingTimeByAmountResponse = Awaited< + ReturnType +>; + +export const useWithdrawalWaitingTime = (amount?: bigint) => { + const { withdraw } = useLidoSDK(); + + return useQuery({ + queryKey: ['withdrawal-waiting-time', amount?.toString()], + enabled: amount !== undefined, + ...STRATEGY_CONSTANT, + queryFn: async () => + withdraw.waitingTime.getWithdrawalWaitingTimeByAmount({ + amount, + }), + select: selectWithdrawalWaitingTime, + }); +}; + +export const selectWithdrawalWaitingTime = ( + data: WaitingTimeByAmountResponse, +) => { + const days = + (countDaysLeft(parseISO(data?.requestInfo?.finalizationAt)) ?? 0) + 1; + + if (Number.isNaN(days) || days < 0) { + return { + days: 0, + text: '—', + }; + } + + return { + days, + text: `~ ${days} ${plural({ value: days, variants: ['day', 'days'] })}`, + }; +}; diff --git a/features/claim-bond/claim-bond-page.tsx b/features/claim-bond/claim-bond-page.tsx index d88a3bbb9..bdcb00839 100644 --- a/features/claim-bond/claim-bond-page.tsx +++ b/features/claim-bond/claim-bond-page.tsx @@ -3,15 +3,17 @@ import { FC } from 'react'; import { Layout } from 'shared/layout'; import { BondPageSwitcher } from 'shared/navigate'; import { ClaimBond } from './claim-bond'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { Faq } from 'shared/components'; +import { FAQ_BOND } from 'faq'; export const ClaimBondPage: FC = () => ( + ); diff --git a/features/claim-bond/claim-bond.tsx b/features/claim-bond/claim-bond.tsx index 2dc63a7c2..752bad132 100644 --- a/features/claim-bond/claim-bond.tsx +++ b/features/claim-bond/claim-bond.tsx @@ -1,8 +1,7 @@ import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; +import { useWeb3Key } from 'shared/hooks'; import { ClaimBondForm } from './claim-bond-form'; -import { Faq } from 'shared/components'; export const ClaimBond = () => { const key = useWeb3Key(); @@ -11,7 +10,6 @@ export const ClaimBond = () => { - ); }; diff --git a/features/claim-type/claim-ics-form/claim-ics-form-info.tsx b/features/claim-type/claim-ics-form/claim-ics-form-info.tsx new file mode 100644 index 000000000..349fb9c12 --- /dev/null +++ b/features/claim-type/claim-ics-form/claim-ics-form-info.tsx @@ -0,0 +1,5 @@ +import { DataTable } from '@lidofinance/lido-ui'; + +export const ClaimIcsFormInfo = () => { + return ; +}; diff --git a/features/claim-type/claim-ics-form/claim-ics-form-loader.tsx b/features/claim-type/claim-ics-form/claim-ics-form-loader.tsx new file mode 100644 index 000000000..f22d91caf --- /dev/null +++ b/features/claim-type/claim-ics-form/claim-ics-form-loader.tsx @@ -0,0 +1,33 @@ +import { FC, PropsWithChildren } from 'react'; +import { EmptyState } from 'shared/components'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { ClaimIcsSuccess } from './claim-ics-success'; +import { useClaimIcsFlow, useClaimIcsFormData } from './context'; +import { ClaimedWithProofInfo } from './controls/claimed-with-proof-info'; +import { Info } from './controls/info'; + +const EMPTY_STATE: Record = { + paused: <>ICS claiming is currently paused, + claimed: <>You have already claimed the ICS operator type, + 'not-eligible': <>You are not eligible to claim the ICS operator type, +}; + +const ClaimIcsFormGate: FC = ({ children }) => { + const { justClaimed } = useClaimIcsFormData(); + const flow = useClaimIcsFlow(); + + if (justClaimed) return ; + if (flow.action === 'no-access') return ; + if (flow.action === 'claimed-with-proof') return ; + + const empty = EMPTY_STATE[flow.action]; + if (empty) return {empty}; + + return <>{children}; +}; + +export const ClaimIcsFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/claim-type/claim-ics-form/claim-ics-form.tsx b/features/claim-type/claim-ics-form/claim-ics-form.tsx new file mode 100644 index 000000000..fc1f10893 --- /dev/null +++ b/features/claim-type/claim-ics-form/claim-ics-form.tsx @@ -0,0 +1,27 @@ +import { FC, memo } from 'react'; + +import { FormBlock } from 'shared/components'; +import { Form } from 'shared/hook-form/form-controller'; +import { ClaimIcsFormInfo } from './claim-ics-form-info'; +import { ClaimIcsFormLoader } from './claim-ics-form-loader'; +import { ClaimIcsDataProvider, ClaimIcsFormProvider } from './context'; +import { Info } from './controls/info'; +import { SubmitButton } from './controls/submit-button'; + +export const ClaimIcsForm: FC = memo(() => { + return ( + + + + +
+ + + + +
+
+
+
+ ); +}); diff --git a/features/claim-type/claim-ics-form/claim-ics-success.tsx b/features/claim-type/claim-ics-form/claim-ics-success.tsx new file mode 100644 index 000000000..26261c496 --- /dev/null +++ b/features/claim-type/claim-ics-form/claim-ics-success.tsx @@ -0,0 +1,64 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC, useCallback, useRef } from 'react'; +import Confetti from 'react-canvas-confetti/dist/presets/realistic'; +import { + TConductorInstance, + TOnInitPresetFn, +} from 'react-canvas-confetti/dist/types'; +import { Stack } from 'shared/components'; +import { + BadgeMain, + BadgeText, + BadgeWrapper, + canvasStyles, + StyledButton, + StyledContainer, +} from './styles'; + +export const ClaimIcsSuccess: FC = () => { + const controller = useRef(); + + const onInitHandler: TOnInitPresetFn = ({ conductor }) => { + controller.current = conductor; + }; + + const fire = useCallback(() => { + controller.current?.shoot(); + }, []); + + return ( + + ({ + ...options, + origin: { + x: 0.3 + Math.random() * 0.4, + y: 0.4 + Math.random() * 0.3, + }, + })} + /> + + + ICS + + + + + Congratulations! + + + You have claimed the Identified Community Staker operator type. +
+ You can see the new parameters for your Node Operator by clicking the + ICS badge at the top of the screen. +
+
+ + Amazing! + +
+ ); +}; diff --git a/features/claim-type/claim-ics-form/confirm-claim-ics-modal.tsx b/features/claim-type/claim-ics-form/confirm-claim-ics-modal.tsx new file mode 100644 index 000000000..51bafb20c --- /dev/null +++ b/features/claim-type/claim-ics-form/confirm-claim-ics-modal.tsx @@ -0,0 +1,31 @@ +import { Button, Modal, Text } from '@lidofinance/lido-ui'; + +import type { ModalComponentType } from 'providers/modal-provider'; +import { Stack } from 'shared/components'; +import { ConfirmModalProps } from 'shared/hooks'; + +export const ConfirmClaimIcsModal: ModalComponentType = ({ + onConfirm, + onReject, + ...props +}) => { + return ( + + + + + You are claiming the Identified Community Staker operator type + + + This action is irreversible, you will not be able to claim your + current operator type back + + + + + + + ); +}; diff --git a/features/claim-type/claim-ics-form/context/claim-ics-data-provider.tsx b/features/claim-type/claim-ics-form/context/claim-ics-data-provider.tsx new file mode 100644 index 000000000..2fe20df3b --- /dev/null +++ b/features/claim-type/claim-ics-form/context/claim-ics-data-provider.tsx @@ -0,0 +1,101 @@ +import { + KEY_ICS_PROOF, + KEY_OPERATOR_BALANCE, + KEY_OPERATOR_CURVE_ID, + KEY_OPERATOR_INFO, + KEY_OPERATOR_KEYS, + useCurveParameters, + useDappStatus, + useIcsCurveId, + useIcsPaused, + useIcsProof, + useNodeOperatorId, + useOperatorCurveId, + useOperatorIsOwner, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback, useState } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useCanClaimICS, useInvalidate } from 'shared/hooks'; +import { type ClaimIcsFormNetworkData } from './types'; + +const useClaimIcsFormNetworkData: NetworkData = () => { + const [justClaimed, setJustClaimed] = useState(false); + + const { address } = useDappStatus(); + const nodeOperatorId = useNodeOperatorId(); + + const { data: icsPaused, isPending: isIcsPausedLoading } = useIcsPaused(); + const currentCurveIdQuery = useOperatorCurveId(nodeOperatorId); + const proofQuery = useIcsProof(); + + const currentCurveId = currentCurveIdQuery.data; + const proof = proofQuery.data; + + const isCurrentCurveIdLoading = currentCurveIdQuery.isPending; + const isProofLoading = proofQuery.isPending; + + const { isPending: isIsOwnerLoading } = useOperatorIsOwner(nodeOperatorId); + const canClaimCurve = useCanClaimICS(); + + const { data: newCurveId, isPending: isNewCurveIdLoading } = useIcsCurveId(); + const { data: currentParameters, isPending: isCurrentParametersLoading } = + useCurveParameters(currentCurveId); + const { data: newParameters, isPending: isNewParametersLoading } = + useCurveParameters(newCurveId); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ + KEY_OPERATOR_CURVE_ID, + KEY_ICS_PROOF, + KEY_OPERATOR_INFO, + KEY_OPERATOR_BALANCE, + KEY_OPERATOR_KEYS, + ]); + + setJustClaimed(true); + }, [invalidate]); + + const isPending = + isIcsPausedLoading || + isIsOwnerLoading || + isCurrentCurveIdLoading || + isCurrentParametersLoading || + isNewCurveIdLoading || + isNewParametersLoading || + isProofLoading; + + return { + data: { + nodeOperatorId, + address, + icsPaused, + currentCurveId, + currentParameters, + newCurveId, + newParameters, + proof, + canClaimCurve, + justClaimed, + } as ClaimIcsFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useClaimIcsFormData = useFormData; + +export const ClaimIcsDataProvider: FC = ({ children }) => { + const networkData = useClaimIcsFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/claim-type/claim-ics-form/context/claim-ics-form-provider.tsx b/features/claim-type/claim-ics-form/context/claim-ics-form-provider.tsx new file mode 100644 index 000000000..6dc0b243a --- /dev/null +++ b/features/claim-type/claim-ics-form/context/claim-ics-form-provider.tsx @@ -0,0 +1,28 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, +} from 'shared/hook-form/form-controller'; +import { type ClaimIcsFormInputType } from './types'; +import { useClaimIcsFlowResolver } from './use-claim-ics-flow'; +import { useClaimIcsValidation } from './use-claim-ics-validation'; + +export const ClaimIcsFormProvider: FC = ({ children }) => { + const resolver = useClaimIcsValidation(); + + const formObject = useForm({ + resolver, + mode: 'onChange', + }); + + const submitter = useFlowSubmit(useClaimIcsFlowResolver()); + + return ( + + + {children} + + + ); +}; diff --git a/features/claim-type/claim-ics-form/context/index.ts b/features/claim-type/claim-ics-form/context/index.ts new file mode 100644 index 000000000..4a2fd2e1b --- /dev/null +++ b/features/claim-type/claim-ics-form/context/index.ts @@ -0,0 +1,4 @@ +export * from './claim-ics-data-provider'; +export * from './claim-ics-form-provider'; +export * from './types'; +export * from './use-claim-ics-flow'; diff --git a/features/claim-type/claim-ics-form/context/types.ts b/features/claim-type/claim-ics-form/context/types.ts new file mode 100644 index 000000000..b90229e31 --- /dev/null +++ b/features/claim-type/claim-ics-form/context/types.ts @@ -0,0 +1,20 @@ +import { AddressProof, CurveParameters } from '@lidofinance/lido-csm-sdk'; +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { Address } from 'viem'; + +export type ClaimIcsFormInputType = { + curveId: bigint; +}; + +export type ClaimIcsFormNetworkData = { + address: Address; + nodeOperatorId: NodeOperatorId; + icsPaused: boolean; + canClaimCurve: boolean; + currentCurveId: bigint; + currentParameters: CurveParameters; + newCurveId: bigint; + newParameters: CurveParameters; + proof: AddressProof; + justClaimed?: boolean; +}; diff --git a/features/claim-type/claim-ics-form/context/use-claim-ics-flow.ts b/features/claim-type/claim-ics-form/context/use-claim-ics-flow.ts new file mode 100644 index 000000000..01ee555f1 --- /dev/null +++ b/features/claim-type/claim-ics-form/context/use-claim-ics-flow.ts @@ -0,0 +1,72 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import invariant from 'tiny-invariant'; +import { useTxModalStagesClaimIcs } from '../hooks/use-tx-modal-stages-claim-ics'; +import { useConfirmClaimIcsModal } from '../hooks/use-confirm-modal'; +import { useClaimIcsFormData } from './claim-ics-data-provider'; +import { ClaimIcsFormInputType, ClaimIcsFormNetworkData } from './types'; + +export type ClaimIcsFlow = + | { action: 'paused' } + | { action: 'claimed' } + | { action: 'claimed-with-proof' } + | { action: 'not-eligible' } + | { action: 'no-access' } + | ({ action: 'claim' } & Executable); + +export const useClaimIcsFlowResolver = (): FlowResolver< + ClaimIcsFormInputType, + ClaimIcsFormNetworkData, + ClaimIcsFlow +> => { + const sdk = useSmSDK(MODULE_NAME.CSM); + invariant(sdk, 'CSM SDK is required for this operation'); + const confirmClaimIcs = useConfirmClaimIcsModal(); + const buildCallback = useTxModalStagesClaimIcs(); + + return useCallback( + (input, data) => { + if (data.icsPaused) return { action: 'paused' }; + + const isEmpty = !data.proof?.proof || data.proof.isConsumed; + + const isClaimed = + data.currentCurveId === data.newCurveId && + data.currentCurveId !== undefined; + if (isClaimed) { + return { action: isEmpty ? 'claimed' : 'claimed-with-proof' }; + } + + if (isEmpty) return { action: 'not-eligible' }; + if (!data.canClaimCurve) return { action: 'no-access' }; + + return { + action: 'claim' as const, + confirm: () => confirmClaimIcs({}), + submit: async () => { + invariant(data.proof.proof, 'Proof is not defined'); + + await sdk.icsGate.claimCurve({ + nodeOperatorId: data.nodeOperatorId, + proof: data.proof.proof, + callback: buildCallback(input, data), + }); + + window.scrollTo({ top: 0 }); + }, + }; + }, + [sdk, confirmClaimIcs, buildCallback], + ); +}; + +export const useClaimIcsFlow = (): ClaimIcsFlow => { + const resolve = useClaimIcsFlowResolver(); + const data = useClaimIcsFormData(true); + return resolve({} as ClaimIcsFormInputType, data); +}; diff --git a/features/claim-type/claim-ics-form/context/use-claim-ics-validation.ts b/features/claim-type/claim-ics-form/context/use-claim-ics-validation.ts new file mode 100644 index 000000000..66e9d9061 --- /dev/null +++ b/features/claim-type/claim-ics-form/context/use-claim-ics-validation.ts @@ -0,0 +1,36 @@ +import { + useFormValidation, + ValidationError, +} from 'shared/hook-form/validation'; +import type { ClaimIcsFormInputType, ClaimIcsFormNetworkData } from './types'; + +export const useClaimIcsValidation = () => { + return useFormValidation( + 'curveId', + async (_, { canClaimCurve, proof, icsPaused }, validate) => { + await validate('curveId', () => { + if (!proof.proof) { + throw new ValidationError('curveId', 'proof is not provided'); + } + }); + + await validate('curveId', () => { + if (proof.isConsumed) { + throw new ValidationError( + 'curveId', + 'claim has already been consumed', + ); + } + }); + + await validate('curveId', () => { + if (!canClaimCurve) { + throw new ValidationError('curveId', 'only owner can claim type'); + } + if (icsPaused) { + throw new ValidationError('curveId', 'ICS is paused'); + } + }); + }, + ); +}; diff --git a/features/claim-type/claim-ics-form/controls/claimed-with-proof-info.tsx b/features/claim-type/claim-ics-form/controls/claimed-with-proof-info.tsx new file mode 100644 index 000000000..20a8b22fa --- /dev/null +++ b/features/claim-type/claim-ics-form/controls/claimed-with-proof-info.tsx @@ -0,0 +1,14 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { FormTitle } from 'shared/components'; + +export const ClaimedWithProofInfo: FC = () => ( + <> + You already have ICS operator type + + Your current Node Operator is already an Identified Community Staker, but + your address still has an unclaimed ICS proof. The proof remains available + for use with another Node Operator on this address. + + +); diff --git a/features/claim-type/claim-ics-form/controls/info.tsx b/features/claim-type/claim-ics-form/controls/info.tsx new file mode 100644 index 000000000..2120093f9 --- /dev/null +++ b/features/claim-type/claim-ics-form/controls/info.tsx @@ -0,0 +1,46 @@ +import { Accordion, Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { CompareParametersList, FormTitle } from 'shared/components'; +import { useCurveMetadata } from 'shared/hooks'; +import styled from 'styled-components'; +import { useClaimIcsFormData } from '../context'; + +export const Info: FC = () => { + const { currentParameters, newParameters, currentCurveId, newCurveId } = + useClaimIcsFormData(); + + const currentMetadata = useCurveMetadata(currentCurveId); + const newMetadata = useCurveMetadata(newCurveId); + return ( + <> + Claim Identified Community Staker operator type + + You are eligible to claim a new operator type. Claiming the Identified + Community Staker operator type will change some parameters for your node + operator according to the section below. + + + + + + ); +}; + +const AccordionStyle = styled(Accordion)` + background: var(--lido-color-backgroundSecondary); + + p { + margin: 0; + } +`; diff --git a/features/claim-type/claim-ics-form/controls/submit-button.tsx b/features/claim-type/claim-ics-form/controls/submit-button.tsx new file mode 100644 index 000000000..bf9a26468 --- /dev/null +++ b/features/claim-type/claim-ics-form/controls/submit-button.tsx @@ -0,0 +1,5 @@ +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; + +export const SubmitButton = () => ( + Claim operator type +); diff --git a/features/claim-type/claim-ics-form/hooks/use-confirm-modal.ts b/features/claim-type/claim-ics-form/hooks/use-confirm-modal.ts new file mode 100644 index 000000000..64d255319 --- /dev/null +++ b/features/claim-type/claim-ics-form/hooks/use-confirm-modal.ts @@ -0,0 +1,4 @@ +import { getUseConfirmModal } from 'shared/hooks'; +import { ConfirmClaimIcsModal } from '../confirm-claim-ics-modal'; + +export const useConfirmClaimIcsModal = getUseConfirmModal(ConfirmClaimIcsModal); diff --git a/features/claim-type/claim-ics-form/hooks/use-tx-modal-stages-claim-ics.tsx b/features/claim-type/claim-ics-form/hooks/use-tx-modal-stages-claim-ics.tsx new file mode 100644 index 000000000..ca4709518 --- /dev/null +++ b/features/claim-type/claim-ics-form/hooks/use-tx-modal-stages-claim-ics.tsx @@ -0,0 +1,35 @@ +import { + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import { + ClaimIcsFormInputType, + ClaimIcsFormNetworkData, +} from '../context/types'; + +export const useTxModalStagesClaimIcs = () => + useTxStages( + (transitStage) => ({ + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (_result: undefined, txHash) => + transitStage( + , + ), + }), + ); diff --git a/features/claim-type/claim-ics-form/index.ts b/features/claim-type/claim-ics-form/index.ts new file mode 100644 index 000000000..6c6af6c01 --- /dev/null +++ b/features/claim-type/claim-ics-form/index.ts @@ -0,0 +1 @@ +export { ClaimIcsForm } from './claim-ics-form'; diff --git a/features/claim-type/claim-ics-form/styles.tsx b/features/claim-type/claim-ics-form/styles.tsx new file mode 100644 index 000000000..99e1a76b4 --- /dev/null +++ b/features/claim-type/claim-ics-form/styles.tsx @@ -0,0 +1,63 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Button, Text } from '@lidofinance/lido-ui'; +import { StackStyle } from 'shared/components'; +import { CURVE_VARIANTS } from 'shared/node-operator/curve-badge/styles'; +import styled, { CSSProperties } from 'styled-components'; + +export const StyledContainer = styled(StackStyle).attrs({ + $direction: 'column', +})` + gap: 40px; + max-width: 420px; + text-align: center; + align-self: center; + align-items: center; +`; + +export const StyledButton = styled(Button)` + max-width: 360px; +`; + +export const BadgeWrapper = styled.div` + position: relative; + display: grid; + width: 150px; + height: 120px; + + &:before { + content: ''; + grid-area: 1 / 1; + filter: blur(38px); + opacity: 0.8; + ${CURVE_VARIANTS[OPERATOR_TYPE.CSM_ICS]} + } +`; + +export const BadgeMain = styled.div` + grid-area: 1 / 1; + display: flex; + align-items: center; + justify-content: center; + z-index: 1; + border-radius: 28px; + border: 4px solid rgba(var(--lido-rgb-foreground), 0.8); + ${CURVE_VARIANTS[OPERATOR_TYPE.CSM_ICS]} + background-origin: border-box; +`; + +export const BadgeText = styled(Text)` + font-weight: 700; + font-size: 36px; + letter-spacing: -0.5pt; + color: var(--lido-color-foreground); +`; + +export const canvasStyles: CSSProperties = { + position: 'fixed', + pointerEvents: 'none', + width: '100%', + height: '100%', + top: 0, + left: 0, + zIndex: 9999, +}; diff --git a/features/claim-type/claim-ics-page.tsx b/features/claim-type/claim-ics-page.tsx new file mode 100644 index 000000000..3c929ee54 --- /dev/null +++ b/features/claim-type/claim-ics-page.tsx @@ -0,0 +1,22 @@ +import { FC } from 'react'; + +import { FAQ_OPERATOR_TYPE } from 'faq'; +import { Faq, TypeBackButton } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { Gate, IcsPageSwitcher, TypePageSwitcher } from 'shared/navigate'; +import { ClaimIcs } from './claim-ics'; + +export const ClaimIcsPage: FC = () => ( + } + > + }> + + + + + +); diff --git a/features/claim-type/claim-ics.tsx b/features/claim-type/claim-ics.tsx new file mode 100644 index 000000000..a97311c3e --- /dev/null +++ b/features/claim-type/claim-ics.tsx @@ -0,0 +1,15 @@ +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; + +import { ClaimIcsForm } from './claim-ics-form'; + +export const ClaimIcs = () => { + const key = useWeb3Key(); + return ( + <> + + + + + ); +}; diff --git a/features/claim-type/claim-idvtc-form/claim-idvtc-form-loader.tsx b/features/claim-type/claim-idvtc-form/claim-idvtc-form-loader.tsx new file mode 100644 index 000000000..c2a60e3e1 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/claim-idvtc-form-loader.tsx @@ -0,0 +1,52 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Button } from '@lidofinance/lido-ui'; +import { PATH } from 'consts'; +import { FC, PropsWithChildren } from 'react'; +import { EmptyState } from 'shared/components'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { getOperatorTypeQuery } from 'shared/hooks'; +import { LocalLink } from 'shared/navigate'; +import { ClaimIdvtcSuccess } from './claim-idvtc-success'; +import { useClaimIdvtcFlow, useClaimIdvtcFormData } from './context'; +import { ClaimedWithProofInfo } from './controls/claimed-with-proof-info'; +import { Info } from './controls/info'; +import { Parameters } from './controls/parameters'; + +const EMPTY_STATE: Record = { + paused: <>IDVTC claiming is currently paused, + claimed: <>You have already claimed the IDVTC operator type, + 'not-eligible': <>You are not eligible to claim the IDVTC operator type, +}; + +const ClaimIdvtcFormGate: FC = ({ children }) => { + const { justClaimed } = useClaimIdvtcFormData(); + const flow = useClaimIdvtcFlow(); + + if (justClaimed) return ; + if (flow.action === 'no-access') return ; + if (flow.action === 'claimed-with-proof') { + return ( + <> + + + + + + + ); + } + + const empty = EMPTY_STATE[flow.action]; + if (empty) return {empty}; + + return <>{children}; +}; + +export const ClaimIdvtcFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/claim-type/claim-idvtc-form/claim-idvtc-form.tsx b/features/claim-type/claim-idvtc-form/claim-idvtc-form.tsx new file mode 100644 index 000000000..19d237bfe --- /dev/null +++ b/features/claim-type/claim-idvtc-form/claim-idvtc-form.tsx @@ -0,0 +1,29 @@ +import { FC, memo } from 'react'; + +import { FormBlock } from 'shared/components'; +import { Form } from 'shared/hook-form/form-controller'; +import { ClaimIdvtcFormLoader } from './claim-idvtc-form-loader'; +import { ClaimIdvtcDataProvider, ClaimIdvtcFormProvider } from './context'; +import { Info } from './controls/info'; +import { ModeSelector } from './controls/mode-selector'; +import { Parameters } from './controls/parameters'; +import { SubmitButton } from './controls/submit-button'; + +export const ClaimIdvtcForm: FC = memo(() => { + return ( + + + + +
+ + + + + +
+
+
+
+ ); +}); diff --git a/features/claim-type/claim-idvtc-form/claim-idvtc-success.tsx b/features/claim-type/claim-idvtc-form/claim-idvtc-success.tsx new file mode 100644 index 000000000..75b950a38 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/claim-idvtc-success.tsx @@ -0,0 +1,64 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC, useCallback, useRef } from 'react'; +import Confetti from 'react-canvas-confetti/dist/presets/realistic'; +import { + TConductorInstance, + TOnInitPresetFn, +} from 'react-canvas-confetti/dist/types'; +import { Stack } from 'shared/components'; +import { + BadgeMain, + BadgeText, + BadgeWrapper, + canvasStyles, + StyledButton, + StyledContainer, +} from './styles'; + +export const ClaimIdvtcSuccess: FC = () => { + const controller = useRef(); + + const onInitHandler: TOnInitPresetFn = ({ conductor }) => { + controller.current = conductor; + }; + + const fire = useCallback(() => { + controller.current?.shoot(); + }, []); + + return ( + + ({ + ...options, + origin: { + x: 0.3 + Math.random() * 0.4, + y: 0.4 + Math.random() * 0.3, + }, + })} + /> + + + IDVTC + + + + + Congratulations! + + + You have claimed the Identified DVT Cluster operator type +
+ You can see the new parameters for your Node Operator by clicking the + IDVTC badge at the top of the screen +
+
+ + Amazing! + +
+ ); +}; diff --git a/features/claim-type/claim-idvtc-form/confirm-claim-idvtc-modal.tsx b/features/claim-type/claim-idvtc-form/confirm-claim-idvtc-modal.tsx new file mode 100644 index 000000000..3c576328b --- /dev/null +++ b/features/claim-type/claim-idvtc-form/confirm-claim-idvtc-modal.tsx @@ -0,0 +1,31 @@ +import { Button, Modal, Text } from '@lidofinance/lido-ui'; + +import type { ModalComponentType } from 'providers/modal-provider'; +import { Stack } from 'shared/components'; +import { ConfirmModalProps } from 'shared/hooks'; + +export const ConfirmClaimIdvtcModal: ModalComponentType = ({ + onConfirm, + onReject, + ...props +}) => { + return ( + + + + + You are claiming the Identified DVT Cluster operator type + + + This action is irreversible, you will not be able to claim your + current operator type back. + + + + + + + ); +}; diff --git a/features/claim-type/claim-idvtc-form/context/claim-idvtc-data-provider.tsx b/features/claim-type/claim-idvtc-form/context/claim-idvtc-data-provider.tsx new file mode 100644 index 000000000..83405c2de --- /dev/null +++ b/features/claim-type/claim-idvtc-form/context/claim-idvtc-data-provider.tsx @@ -0,0 +1,115 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { + KEY_IDVTC_PROOF, + KEY_OPERATOR_BALANCE, + KEY_OPERATOR_CURVE_ID, + KEY_OPERATOR_INFO, + KEY_OPERATOR_KEYS, + useCurveParameters, + useDappStatus, + useIdvtcCurveId, + useIdvtcPaused, + useIdvtcProof, + useNodeOperatorId, + useOperatorCurveId, + useOperatorIsOwner, + useOperatorType, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback, useState } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useCanClaimIDVTC, useInvalidate } from 'shared/hooks'; +import { type ClaimIdvtcFormNetworkData } from './types'; + +const useClaimIdvtcFormNetworkData: NetworkData< + ClaimIdvtcFormNetworkData +> = () => { + const [justClaimed, setJustClaimed] = useState(false); + + const { address } = useDappStatus(); + const nodeOperatorId = useNodeOperatorId(); + const hasOperator = nodeOperatorId !== undefined; + + const { data: idvtcPaused, isPending: isIdvtcPausedLoading } = + useIdvtcPaused(); + const currentCurveIdQuery = useOperatorCurveId(nodeOperatorId); + const proofQuery = useIdvtcProof(); + + const currentCurveId = currentCurveIdQuery.data; + const proof = proofQuery.data; + + const isCurrentCurveIdLoading = currentCurveIdQuery.isPending; + const isProofLoading = proofQuery.isPending; + + const { isPending: isIsOwnerLoading } = useOperatorIsOwner(nodeOperatorId); + const canClaimCurve = useCanClaimIDVTC(); + + const { data: currentOperatorType, isPending: isCurrentOperatorTypeLoading } = + useOperatorType(nodeOperatorId); + const isCurrentIcs = currentOperatorType === OPERATOR_TYPE.CSM_ICS; + + const { data: newCurveId, isPending: isNewCurveIdLoading } = + useIdvtcCurveId(); + const { data: currentParameters, isPending: isCurrentParametersLoading } = + useCurveParameters(currentCurveId); + const { data: newParameters, isPending: isNewParametersLoading } = + useCurveParameters(newCurveId); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ + KEY_OPERATOR_CURVE_ID, + KEY_IDVTC_PROOF, + KEY_OPERATOR_INFO, + KEY_OPERATOR_BALANCE, + KEY_OPERATOR_KEYS, + ]); + + setJustClaimed(true); + }, [invalidate]); + + const isPending = + isIdvtcPausedLoading || + isIsOwnerLoading || + (hasOperator && isCurrentCurveIdLoading) || + (hasOperator && isCurrentOperatorTypeLoading) || + (hasOperator && isCurrentParametersLoading) || + isNewCurveIdLoading || + isNewParametersLoading || + isProofLoading; + + return { + data: { + nodeOperatorId, + address, + idvtcPaused, + currentCurveId, + currentOperatorType, + isCurrentIcs, + currentParameters, + newCurveId, + newParameters, + proof, + canClaimCurve, + justClaimed, + } as ClaimIdvtcFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useClaimIdvtcFormData = useFormData; + +export const ClaimIdvtcDataProvider: FC = ({ children }) => { + const networkData = useClaimIdvtcFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/claim-type/claim-idvtc-form/context/claim-idvtc-form-provider.tsx b/features/claim-type/claim-idvtc-form/context/claim-idvtc-form-provider.tsx new file mode 100644 index 000000000..ddbbc1c76 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/context/claim-idvtc-form-provider.tsx @@ -0,0 +1,29 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, +} from 'shared/hook-form/form-controller'; +import { type ClaimIdvtcFormInputType } from './types'; +import { useClaimIdvtcFlowResolver } from './use-claim-idvtc-flow'; +import { useClaimIdvtcValidation } from './use-claim-idvtc-validation'; + +export const ClaimIdvtcFormProvider: FC = ({ children }) => { + const resolver = useClaimIdvtcValidation(); + + const formObject = useForm({ + resolver, + mode: 'onChange', + defaultValues: { mode: 'upgrade' }, + }); + + const submitter = useFlowSubmit(useClaimIdvtcFlowResolver()); + + return ( + + + {children} + + + ); +}; diff --git a/features/claim-type/claim-idvtc-form/context/index.ts b/features/claim-type/claim-idvtc-form/context/index.ts new file mode 100644 index 000000000..26c2ab14e --- /dev/null +++ b/features/claim-type/claim-idvtc-form/context/index.ts @@ -0,0 +1,4 @@ +export * from './claim-idvtc-data-provider'; +export * from './claim-idvtc-form-provider'; +export * from './types'; +export * from './use-claim-idvtc-flow'; diff --git a/features/claim-type/claim-idvtc-form/context/types.ts b/features/claim-type/claim-idvtc-form/context/types.ts new file mode 100644 index 000000000..231ff9012 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/context/types.ts @@ -0,0 +1,29 @@ +import { + AddressProof, + CurveParameters, + OPERATOR_TYPE, +} from '@lidofinance/lido-csm-sdk'; +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { Address } from 'viem'; + +export type ClaimIdvtcMode = 'upgrade' | 'create'; + +export type ClaimIdvtcFormInputType = { + curveId: bigint; + mode: ClaimIdvtcMode; +}; + +export type ClaimIdvtcFormNetworkData = { + address: Address; + nodeOperatorId: NodeOperatorId; + idvtcPaused: boolean; + canClaimCurve: boolean; + currentCurveId: bigint; + currentOperatorType?: OPERATOR_TYPE; + isCurrentIcs: boolean; + currentParameters: CurveParameters; + newCurveId: bigint; + newParameters: CurveParameters; + proof: AddressProof; + justClaimed?: boolean; +}; diff --git a/features/claim-type/claim-idvtc-form/context/use-claim-idvtc-flow.ts b/features/claim-type/claim-idvtc-form/context/use-claim-idvtc-flow.ts new file mode 100644 index 000000000..855f06278 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/context/use-claim-idvtc-flow.ts @@ -0,0 +1,82 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import invariant from 'tiny-invariant'; +import { useConfirmClaimIdvtcModal } from '../hooks/use-confirm-modal'; +import { useTxModalStagesClaimIdvtc } from '../hooks/use-tx-modal-stages-claim-idvtc'; +import { useClaimIdvtcFormData } from './claim-idvtc-data-provider'; +import { ClaimIdvtcFormInputType, ClaimIdvtcFormNetworkData } from './types'; + +export type ClaimIdvtcFlow = + | { action: 'paused' } + | { action: 'claimed' } + | { action: 'claimed-with-proof' } + | { action: 'not-eligible' } + | { action: 'no-access' } + | { action: 'create' } + | ({ action: 'claim' } & Executable); + +export const useClaimIdvtcFlowResolver = (): FlowResolver< + ClaimIdvtcFormInputType, + ClaimIdvtcFormNetworkData, + ClaimIdvtcFlow +> => { + const sdk = useSmSDK(MODULE_NAME.CSM); + invariant(sdk, 'CSM SDK is required for this operation'); + const confirmClaimIdvtc = useConfirmClaimIdvtcModal(); + const buildCallback = useTxModalStagesClaimIdvtc(); + + return useCallback( + (input, data) => { + if (data.idvtcPaused) return { action: 'paused' }; + + const isEmpty = !data.proof?.proof || data.proof.isConsumed; + + const isClaimed = + data.currentCurveId === data.newCurveId && + data.currentCurveId !== undefined; + if (isClaimed) { + return { action: isEmpty ? 'claimed' : 'claimed-with-proof' }; + } + + if (isEmpty) return { action: 'not-eligible' }; + if (!data.canClaimCurve) return { action: 'no-access' }; + + // 'create' is a navigation path (link), not a submit — don't run the tx + if (data.isCurrentIcs && input.mode === 'create') { + return { action: 'create' }; + } + + return { + action: 'claim' as const, + confirm: () => confirmClaimIdvtc({}), + submit: async () => { + invariant(data.proof.proof, 'Proof is not defined'); + invariant( + data.nodeOperatorId !== undefined, + 'NodeOperatorId is not defined', + ); + + await sdk.idvtcGate.claimCurve({ + nodeOperatorId: data.nodeOperatorId, + proof: data.proof.proof, + callback: buildCallback(input, data), + }); + + window.scrollTo({ top: 0 }); + }, + }; + }, + [sdk, confirmClaimIdvtc, buildCallback], + ); +}; + +export const useClaimIdvtcFlow = (): ClaimIdvtcFlow => { + const resolve = useClaimIdvtcFlowResolver(); + const data = useClaimIdvtcFormData(true); + return resolve({} as ClaimIdvtcFormInputType, data); +}; diff --git a/features/claim-type/claim-idvtc-form/context/use-claim-idvtc-validation.ts b/features/claim-type/claim-idvtc-form/context/use-claim-idvtc-validation.ts new file mode 100644 index 000000000..c021951f8 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/context/use-claim-idvtc-validation.ts @@ -0,0 +1,39 @@ +import { + useFormValidation, + ValidationError, +} from 'shared/hook-form/validation'; +import type { + ClaimIdvtcFormInputType, + ClaimIdvtcFormNetworkData, +} from './types'; + +export const useClaimIdvtcValidation = () => { + return useFormValidation( + 'curveId', + async (_, { canClaimCurve, proof, idvtcPaused }, validate) => { + await validate('curveId', () => { + if (!proof.proof) { + throw new ValidationError('curveId', 'proof is not provided'); + } + }); + + await validate('curveId', () => { + if (proof.isConsumed) { + throw new ValidationError( + 'curveId', + 'claim has already been consumed', + ); + } + }); + + await validate('curveId', () => { + if (idvtcPaused) { + throw new ValidationError('curveId', 'IDVTC is paused'); + } + if (!canClaimCurve) { + throw new ValidationError('curveId', 'only owner can claim type'); + } + }); + }, + ); +}; diff --git a/features/claim-type/claim-idvtc-form/controls/claimed-with-proof-info.tsx b/features/claim-type/claim-idvtc-form/controls/claimed-with-proof-info.tsx new file mode 100644 index 000000000..69083f753 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/controls/claimed-with-proof-info.tsx @@ -0,0 +1,14 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { FormTitle } from 'shared/components'; + +export const ClaimedWithProofInfo: FC = () => ( + <> + You already have IDVTC operator type + + Your current Node Operator is already an Identified DVT Cluster, but your + address still has an unclaimed IDVTC proof. You can create a separate Node + Operator with the Identified DVT Cluster type using this proof. + + +); diff --git a/features/claim-type/claim-idvtc-form/controls/info.tsx b/features/claim-type/claim-idvtc-form/controls/info.tsx new file mode 100644 index 000000000..8de7871a3 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/controls/info.tsx @@ -0,0 +1,18 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { FormTitle } from 'shared/components'; +import { useClaimIdvtcFormData } from '../context'; + +export const Info: FC = () => { + const { isCurrentIcs } = useClaimIdvtcFormData(); + return ( + <> + Claim Identified DVT Cluster operator type + + {isCurrentIcs + ? 'You are eligible to claim a new operator type. Choose the option you prefer. Claiming the Identified Community Staker operator type will change some parameters for your node operator according to the section below.' + : 'You are eligible to claim a new operator type. Claiming the Identified DVT Cluster operator type will change some parameters for your node operator according to the section below.'} + + + ); +}; diff --git a/features/claim-type/claim-idvtc-form/controls/mode-selector.tsx b/features/claim-type/claim-idvtc-form/controls/mode-selector.tsx new file mode 100644 index 000000000..759bdb399 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/controls/mode-selector.tsx @@ -0,0 +1,60 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { useController } from 'react-hook-form'; +import { RadioButton, RadioIcon, Stack } from 'shared/components'; +import { + useClaimIdvtcFormData, + type ClaimIdvtcFormInputType, + type ClaimIdvtcMode, +} from '../context'; + +const OPTIONS: { + value: ClaimIdvtcMode; + title: string; + description: string; +}[] = [ + { + value: 'upgrade', + title: 'Upgrade ICS to IDVTC', + description: + 'Claiming the Identified DVT Cluster operator type will change some parameters for your node operator according to the section below.', + }, + { + value: 'create', + title: 'Create a new IDVTC operator', + description: + 'Creating a separate Node Operator with the Identified DVT Cluster operator type will keep your current ICS status alongside with the new IDVTC type.', + }, +]; + +export const ModeSelector: FC = () => { + const { isCurrentIcs } = useClaimIdvtcFormData(); + const { field } = useController({ + name: 'mode', + }); + + if (!isCurrentIcs) return null; + + return ( + + {OPTIONS.map(({ value, title, description }) => ( + + + + + {title} + + {description} + + + + + ))} + + ); +}; diff --git a/features/claim-type/claim-idvtc-form/controls/parameters.tsx b/features/claim-type/claim-idvtc-form/controls/parameters.tsx new file mode 100644 index 000000000..48c7f9a62 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/controls/parameters.tsx @@ -0,0 +1,38 @@ +import { FC } from 'react'; +import { useWatch } from 'react-hook-form'; +import { + CompareParametersList, + CompareParametersListItem, +} from 'shared/components'; +import { useCurveMetadata } from 'shared/hooks'; +import { ClaimIdvtcFormInputType, useClaimIdvtcFormData } from '../context'; +import { AccordionStyle } from '../styles'; + +export const Parameters: FC = () => { + const { currentParameters, newParameters, currentCurveId, newCurveId } = + useClaimIdvtcFormData(true); + + const mode = useWatch({ name: 'mode' }); + + const currentMetadata = useCurveMetadata(currentCurveId); + const newMetadata = useCurveMetadata(newCurveId); + + const items: CompareParametersListItem[] = [ + { + parameters: currentParameters, + title: `Current (${currentMetadata?.short ?? ''})`, + }, + { + parameters: newParameters, + title: `New (${newMetadata?.short ?? ''})`, + }, + ]; + + return ( + + + + ); +}; diff --git a/features/claim-type/claim-idvtc-form/controls/submit-button.tsx b/features/claim-type/claim-idvtc-form/controls/submit-button.tsx new file mode 100644 index 000000000..4675c66fd --- /dev/null +++ b/features/claim-type/claim-idvtc-form/controls/submit-button.tsx @@ -0,0 +1,33 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Button } from '@lidofinance/lido-ui'; +import { PATH } from 'consts'; +import { useWatch } from 'react-hook-form'; +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; +import { getOperatorTypeQuery } from 'shared/hooks'; +import { LocalLink } from 'shared/navigate'; +import { + useClaimIdvtcFormData, + type ClaimIdvtcFormInputType, +} from '../context'; + +export const SubmitButton = () => { + const { isCurrentIcs } = useClaimIdvtcFormData(); + const mode = useWatch({ name: 'mode' }); + + if (mode === 'create') { + return ( + + + + ); + } + + return ( + + {isCurrentIcs ? 'Upgrade ICS to IDVTC' : 'Claim operator type'} + + ); +}; diff --git a/features/claim-type/claim-idvtc-form/hooks/use-confirm-modal.ts b/features/claim-type/claim-idvtc-form/hooks/use-confirm-modal.ts new file mode 100644 index 000000000..5f4ed53a7 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/hooks/use-confirm-modal.ts @@ -0,0 +1,6 @@ +import { getUseConfirmModal } from 'shared/hooks'; +import { ConfirmClaimIdvtcModal } from '../confirm-claim-idvtc-modal'; + +export const useConfirmClaimIdvtcModal = getUseConfirmModal( + ConfirmClaimIdvtcModal, +); diff --git a/features/claim-type/claim-idvtc-form/hooks/use-tx-modal-stages-claim-idvtc.tsx b/features/claim-type/claim-idvtc-form/hooks/use-tx-modal-stages-claim-idvtc.tsx new file mode 100644 index 000000000..73c9b1d52 --- /dev/null +++ b/features/claim-type/claim-idvtc-form/hooks/use-tx-modal-stages-claim-idvtc.tsx @@ -0,0 +1,35 @@ +import { + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import { + ClaimIdvtcFormInputType, + ClaimIdvtcFormNetworkData, +} from '../context/types'; + +export const useTxModalStagesClaimIdvtc = () => + useTxStages( + (transitStage) => ({ + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (_result: undefined, txHash) => + transitStage( + , + ), + }), + ); diff --git a/features/claim-type/claim-idvtc-form/index.ts b/features/claim-type/claim-idvtc-form/index.ts new file mode 100644 index 000000000..a1adbafab --- /dev/null +++ b/features/claim-type/claim-idvtc-form/index.ts @@ -0,0 +1 @@ +export { ClaimIdvtcForm } from './claim-idvtc-form'; diff --git a/features/claim-type/claim-idvtc-form/styles.tsx b/features/claim-type/claim-idvtc-form/styles.tsx new file mode 100644 index 000000000..f9dee8a4d --- /dev/null +++ b/features/claim-type/claim-idvtc-form/styles.tsx @@ -0,0 +1,71 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Accordion, Button, Text } from '@lidofinance/lido-ui'; +import { StackStyle } from 'shared/components'; +import { CURVE_VARIANTS } from 'shared/node-operator/curve-badge/styles'; +import styled, { CSSProperties } from 'styled-components'; + +export const StyledContainer = styled(StackStyle).attrs({ + $direction: 'column', +})` + gap: 40px; + max-width: 420px; + text-align: center; + align-self: center; + align-items: center; +`; + +export const StyledButton = styled(Button)` + max-width: 360px; +`; + +export const BadgeWrapper = styled.div` + position: relative; + display: grid; + width: 150px; + height: 120px; + + &:before { + content: ''; + grid-area: 1 / 1; + filter: blur(38px); + opacity: 0.8; + ${CURVE_VARIANTS[OPERATOR_TYPE.CSM_IDVTC]} + } +`; + +export const BadgeMain = styled.div` + grid-area: 1 / 1; + display: flex; + align-items: center; + justify-content: center; + z-index: 1; + border-radius: 28px; + border: 4px solid rgba(var(--lido-rgb-foreground), 0.8); + ${CURVE_VARIANTS[OPERATOR_TYPE.CSM_IDVTC]} + background-origin: border-box; +`; + +export const BadgeText = styled(Text)` + font-weight: 700; + font-size: 36px; + letter-spacing: -0.5pt; + color: var(--lido-color-foreground); +`; + +export const canvasStyles: CSSProperties = { + position: 'fixed', + pointerEvents: 'none', + width: '100%', + height: '100%', + top: 0, + left: 0, + zIndex: 9999, +}; + +export const AccordionStyle = styled(Accordion)` + background: var(--lido-color-backgroundSecondary); + + p { + margin: 0; + } +`; diff --git a/features/claim-type/claim-idvtc-page.tsx b/features/claim-type/claim-idvtc-page.tsx new file mode 100644 index 000000000..a619b6483 --- /dev/null +++ b/features/claim-type/claim-idvtc-page.tsx @@ -0,0 +1,21 @@ +import { FAQ_OPERATOR_TYPE } from 'faq'; +import { FC } from 'react'; +import { Faq, TypeBackButton } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { DvtPageSwitcher, Gate, TypePageSwitcher } from 'shared/navigate'; +import { ClaimIdvtc } from './claim-idvtc'; + +export const ClaimIdvtcPage: FC = () => ( + } + > + }> + + + + + +); diff --git a/features/claim-type/claim-idvtc.tsx b/features/claim-type/claim-idvtc.tsx new file mode 100644 index 000000000..f5bd53fbf --- /dev/null +++ b/features/claim-type/claim-idvtc.tsx @@ -0,0 +1,13 @@ +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; + +import { ClaimIdvtcForm } from './claim-idvtc-form'; + +export const ClaimIdvtc = () => { + const key = useWeb3Key(); + return ( + + + + ); +}; diff --git a/features/claim-type/index.ts b/features/claim-type/index.ts new file mode 100644 index 000000000..1b8454235 --- /dev/null +++ b/features/claim-type/index.ts @@ -0,0 +1,4 @@ +export * from './claim-ics-page'; +export * from './claim-ics'; +export * from './claim-idvtc-page'; +export * from './claim-idvtc'; diff --git a/features/create-node-operator/create-curated-node-operator.tsx b/features/create-node-operator/create-curated-node-operator.tsx new file mode 100644 index 000000000..155ca540a --- /dev/null +++ b/features/create-node-operator/create-curated-node-operator.tsx @@ -0,0 +1,20 @@ +import { BannerOperatorCustomAddresses } from 'features/starter-pack/banner-operator-custom-addresses'; +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; + +import { CuratedOperatorForm } from './curated-operator-form'; +import { OtherModuleBanner } from './other-module-banner'; + +export const CreateCuratedNodeOperator = () => { + const key = useWeb3Key(); + + return ( + <> + + + + + + + ); +}; diff --git a/features/create-node-operator/create-node-operator-page.tsx b/features/create-node-operator/create-node-operator-page.tsx index 0bfc7f0a9..15412c7f9 100644 --- a/features/create-node-operator/create-node-operator-page.tsx +++ b/features/create-node-operator/create-node-operator-page.tsx @@ -1,15 +1,23 @@ import { FC } from 'react'; +import { isModuleCM } from 'consts'; +import { FAQ_KEYS } from 'faq'; +import { Faq } from 'shared/components'; import { Layout } from 'shared/layout'; +import { CreateCuratedNodeOperator } from './create-curated-node-operator'; import { CreateNodeOperator } from './create-node-operator'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; export const CreateNodeOperatorPage: FC = () => ( - + {isModuleCM ? : } + ); diff --git a/features/create-node-operator/create-node-operator.tsx b/features/create-node-operator/create-node-operator.tsx index a1d7133d9..ce043f6a2 100644 --- a/features/create-node-operator/create-node-operator.tsx +++ b/features/create-node-operator/create-node-operator.tsx @@ -1,13 +1,13 @@ import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; +import { useWeb3Key } from 'shared/hooks'; -import { SubmitKeysForm } from './submit-keys-form'; -import { Faq } from 'shared/components'; import { OtherModuleBanner } from './other-module-banner'; import { ShareLimitBanner } from './share-limit-banner'; +import { SubmitKeysForm } from './submit-keys-form'; export const CreateNodeOperator = () => { const key = useWeb3Key(); + return ( <> @@ -15,7 +15,6 @@ export const CreateNodeOperator = () => { - ); }; diff --git a/features/create-node-operator/curated-operator-form/context/curated-operator-data-provider.tsx b/features/create-node-operator/curated-operator-form/context/curated-operator-data-provider.tsx new file mode 100644 index 000000000..1ccb51944 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/context/curated-operator-data-provider.tsx @@ -0,0 +1,63 @@ +import { + useSmStatus, + useDappStatus, + KEY_CURATED_GATES_PROOF, + useEthereumBalance, + useCuratedGatesEligibility, +} from 'modules/web3'; +import { type FC, type PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + type NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import { type CuratedOperatorFormNetworkData } from './types'; + +const useCuratedOperatorFormNetworkData: NetworkData< + CuratedOperatorFormNetworkData +> = () => { + const { data: status, isPending: isStatusLoading } = useSmStatus(); + const { address } = useDappStatus(); + + const ethBalanceQuery = useEthereumBalance(); + const ethBalance = ethBalanceQuery.data; + const isEthBalanceLoading = ethBalanceQuery.isPending; + + const { data: availableGates, isPending: isGatesLoading } = + useCuratedGatesEligibility(); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ethBalanceQuery.queryKey, KEY_CURATED_GATES_PROOF]); + }, [ethBalanceQuery.queryKey, invalidate]); + + const isPending = isStatusLoading || isGatesLoading || isEthBalanceLoading; + + return { + data: { + ethBalance, + address, + availableGates, + isPaused: status?.isPaused ?? false, + } as CuratedOperatorFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useCuratedOperatorFormData = + useFormData; + +export const CuratedOperatorDataProvider: FC = ({ + children, +}) => { + const networkData = useCuratedOperatorFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/create-node-operator/curated-operator-form/context/curated-operator-form-provider.tsx b/features/create-node-operator/curated-operator-form/context/curated-operator-form-provider.tsx new file mode 100644 index 000000000..d8e980283 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/context/curated-operator-form-provider.tsx @@ -0,0 +1,36 @@ +import { type FC, type PropsWithChildren } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, +} from 'shared/hook-form/form-controller'; +import { type CuratedOperatorFormInputType } from './types'; +import { useCuratedOperatorFlowResolver } from './use-curated-operator-flow'; +import { useCuratedOperatorDefaultValues } from './use-curated-operator-default-values'; +import { useCuratedOperatorValidation } from './use-curated-operator-validation'; + +export const CuratedOperatorFormProvider: FC = ({ + children, +}) => { + const resolver = useCuratedOperatorValidation(); + const defaultValues = useCuratedOperatorDefaultValues(); + + const formObject = useForm({ + defaultValues, + resolver, + mode: 'onChange', + }); + + const submitter = useFlowSubmit(useCuratedOperatorFlowResolver()); + + return ( + + + {children} + + + ); +}; diff --git a/features/create-node-operator/curated-operator-form/context/index.ts b/features/create-node-operator/curated-operator-form/context/index.ts new file mode 100644 index 000000000..e1c94e032 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/context/index.ts @@ -0,0 +1,6 @@ +export * from './types'; +export * from './curated-operator-data-provider'; +export * from './curated-operator-form-provider'; +export * from './use-curated-operator-default-values'; +export * from './use-curated-operator-validation'; +export * from './use-curated-operator-flow'; diff --git a/features/create-node-operator/curated-operator-form/context/types.ts b/features/create-node-operator/curated-operator-form/context/types.ts new file mode 100644 index 000000000..61032d095 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/context/types.ts @@ -0,0 +1,18 @@ +import { CURATED_GATES, GateItemEligibility } from '@lidofinance/lido-csm-sdk'; +import type { Address } from 'viem'; + +export type CuratedOperatorFormInputType = { + step: number; + gateName?: CURATED_GATES; + rewardAddress?: Address; + managerAddress?: Address; + name: string; + description: string; +}; + +export type CuratedOperatorFormNetworkData = { + ethBalance: bigint; + address: Address; + availableGates: GateItemEligibility[]; + isPaused: boolean; +}; diff --git a/features/create-node-operator/curated-operator-form/context/use-curated-operator-default-values.ts b/features/create-node-operator/curated-operator-form/context/use-curated-operator-default-values.ts new file mode 100644 index 000000000..8dd9690b6 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/context/use-curated-operator-default-values.ts @@ -0,0 +1,19 @@ +import { useFormDefaultValues } from 'shared/hook-form/form-controller'; +import { + type CuratedOperatorFormInputType, + type CuratedOperatorFormNetworkData, +} from './types'; + +export const useCuratedOperatorDefaultValues = () => { + return useFormDefaultValues< + CuratedOperatorFormInputType, + CuratedOperatorFormNetworkData + >(() => ({ + step: 1, + gateName: undefined, + rewardAddress: undefined, + managerAddress: undefined, + name: '', + description: '', + })); +}; diff --git a/features/create-node-operator/curated-operator-form/context/use-curated-operator-flow.ts b/features/create-node-operator/curated-operator-form/context/use-curated-operator-flow.ts new file mode 100644 index 000000000..183da5e8e --- /dev/null +++ b/features/create-node-operator/curated-operator-form/context/use-curated-operator-flow.ts @@ -0,0 +1,82 @@ +import { MODULE_NAME, getNodeOperatorRoles } from '@lidofinance/lido-csm-sdk'; +import { PATH } from 'consts'; +import { useOperatorCustomAddresses } from 'features/starter-pack/banner-operator-custom-addresses'; +import { useAppendOperator, useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useNavigate } from 'shared/navigate'; +import invariant from 'tiny-invariant'; +import { useTxModalStagesCuratedOperator } from '../hooks/use-tx-modal-stages-curated-operator'; +import { useCuratedOperatorFormData } from './curated-operator-data-provider'; +import { + CuratedOperatorFormInputType, + CuratedOperatorFormNetworkData, +} from './types'; + +export type CuratedOperatorFlow = + | { action: 'no-gates' } + | ({ action: 'create-operator' } & Executable); + +export const useCuratedOperatorFlowResolver = (): FlowResolver< + CuratedOperatorFormInputType, + CuratedOperatorFormNetworkData, + CuratedOperatorFlow +> => { + const sdk = useSmSDK(MODULE_NAME.CM); + const appendNO = useAppendOperator(true); + const [, setOperatorCustomAddresses] = useOperatorCustomAddresses(); + const n = useNavigate(); + const buildCallback = useTxModalStagesCuratedOperator(); + + return useCallback( + (input, data) => { + if (data.availableGates.length === 0) return { action: 'no-gates' }; + + return { + action: 'create-operator' as const, + submit: async () => { + invariant(sdk, 'CM SDK not initialized'); + invariant(input.gateName !== undefined, 'Gate not selected'); + invariant(input.rewardAddress, 'Rewards Address required'); + invariant(input.managerAddress, 'Manager Address required'); + + const selectedGate = data.availableGates.find( + (gate) => gate.gateName === input.gateName, + ); + invariant(selectedGate, 'Selected gate not found'); + invariant(selectedGate.proof, 'Proof not available'); + + const { result } = await sdk.curatedGates.createNodeOperator({ + gateName: input.gateName, + name: input.name, + description: input.description, + managerAddress: input.managerAddress, + rewardAddress: input.rewardAddress, + proof: selectedGate.proof, + callback: buildCallback(input, data), + }); + + if (result) { + const roles = getNodeOperatorRoles(result, data.address); + if (roles.length > 0) { + appendNO(result); + void n(PATH.HOME); + } else { + setOperatorCustomAddresses(result.nodeOperatorId); + } + } + }, + }; + }, + [sdk, appendNO, setOperatorCustomAddresses, n, buildCallback], + ); +}; + +export const useCuratedOperatorFlow = (): CuratedOperatorFlow => { + const resolve = useCuratedOperatorFlowResolver(); + const data = useCuratedOperatorFormData(true); + return resolve({} as CuratedOperatorFormInputType, data); +}; diff --git a/features/create-node-operator/curated-operator-form/context/use-curated-operator-validation.ts b/features/create-node-operator/curated-operator-form/context/use-curated-operator-validation.ts new file mode 100644 index 000000000..3a3373c45 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/context/use-curated-operator-validation.ts @@ -0,0 +1,78 @@ +import { + useFormValidation, + validateAddress, + validateLength, + ValidationError, +} from 'shared/hook-form/validation'; +import type { + CuratedOperatorFormInputType, + CuratedOperatorFormNetworkData, +} from './types'; + +export const useCuratedOperatorValidation = () => { + return useFormValidation< + CuratedOperatorFormInputType, + CuratedOperatorFormNetworkData + >( + 'gateName', + async ( + { gateName, rewardAddress, managerAddress, name, description }, + { availableGates }, + validate, + ) => { + await validate('gateName', () => { + if (gateName === undefined) { + throw new ValidationError('gateName', 'Please select Operator Type'); + } + + const selectedGate = availableGates.find( + (gate) => gate.gateName === gateName, + ); + + if (!selectedGate) { + throw new ValidationError( + 'gateName', + 'Invalid Operator Type selected', + ); + } + + if (selectedGate.isPaused) { + throw new ValidationError( + 'gateName', + 'This Operator Type is currently paused', + ); + } + + if (selectedGate.isConsumed) { + throw new ValidationError( + 'gateName', + 'You have already used this Operator Type', + ); + } + + if (!selectedGate.proof) { + throw new ValidationError( + 'gateName', + 'You are not eligible for this Operator Type', + ); + } + }); + + await validate('rewardAddress', () => { + validateAddress('rewardAddress', rewardAddress); + }); + + await validate('managerAddress', () => { + validateAddress('managerAddress', managerAddress); + }); + + await validate('name', () => { + validateLength('name', name, 1, 64); + }); + + await validate('description', () => { + validateLength('description', description, 1, 1024); + }); + }, + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/gate-card.tsx b/features/create-node-operator/curated-operator-form/controls/gate-card.tsx new file mode 100644 index 000000000..af839906f --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/gate-card.tsx @@ -0,0 +1,141 @@ +import { Check, Divider, InlineLoader, Text } from '@lidofinance/lido-ui'; +import { + type ChangeEvent, + type ComponentPropsWithoutRef, + type FC, + type ReactNode, +} from 'react'; +import { CUSTOM_CURVE, OPERATOR_TYPE_METADATA } from 'consts'; +import { useCurveParameters } from 'modules/web3'; +import { + formatPercentKeyIntervals, + formatEthKeyIntervals, +} from 'shared/components/parameters-list/format'; +import { RadioButton, Stack } from 'shared/components'; +import { useDisplayOperatorType } from 'shared/hooks'; +import { CurveBadge } from 'shared/node-operator/curve-badge/curve-badge'; +import styled from 'styled-components'; + +type GateCardProps = { + curveId: bigint; + checked: boolean; + name: string; + value: string; + onChange: (e: ChangeEvent) => void; + onBlur?: () => void; +}; + +export const GateCard: FC = ({ curveId, ...fieldProps }) => { + const { data: parameters } = useCurveParameters(curveId); + + // curveId is a defined bigint, so the display type is always resolvable; + // the CUSTOM_CURVE fallback only narrows the type for TypeScript. + const type = useDisplayOperatorType(curveId) ?? CUSTOM_CURVE; + const metadata = OPERATOR_TYPE_METADATA[type]; + const loading = !parameters; + + return ( + + + + + + + {metadata.name} + + + {metadata.description} + + + + + + + + + + {fieldProps.checked && } + + + + ); +}; + +const ParamSection: FC< + ComponentPropsWithoutRef<'div'> & { + title: string; + items: ReactNode[]; + loading?: boolean; + } +> = ({ title, items, loading, ...props }) => ( +
+ + {title} + + {loading ? ( + + ) : ( + + {items.map((item, i) => ( +
  • + + {item} + +
  • + ))} +
    + )} +
    +); + +const CardLayout = styled.div` + display: grid; + grid-template-columns: 1fr 1px 1fr; + gap: 20px; + width: 100%; +`; + +const Description = styled(Text)` + line-height: 1.4; +`; + +const ParamList = styled.ul` + margin: 4px 0 0; + padding-left: 16px; + list-style: disc; + + li { + margin-bottom: 2px; + } +`; + +const SatusStyled = styled.div` + display: flex; + align-items: center; + flex: 0 0 auto; + width: 24px; +`; + +const CheckIcon = styled(Check)` + border-radius: 100%; + background: var(--lido-color-primary); + color: var(--lido-color-primaryContrast); +`; diff --git a/features/create-node-operator/curated-operator-form/controls/gate-selector.tsx b/features/create-node-operator/curated-operator-form/controls/gate-selector.tsx new file mode 100644 index 000000000..5abed0842 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/gate-selector.tsx @@ -0,0 +1,32 @@ +import { type FC } from 'react'; +import { useController } from 'react-hook-form'; +import { Stack } from 'shared/components'; +import { useCuratedOperatorFormData } from '../context'; +import type { CuratedOperatorFormInputType } from '../context/types'; +import { GateCard } from './gate-card'; + +export const GateSelector: FC = () => { + const { availableGates = [] } = useCuratedOperatorFormData(); + + const { field } = useController({ + name: 'gateName', + }); + + return ( + + {availableGates.map((gate) => { + return ( + + ); + })} + + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/manager-address-input.tsx b/features/create-node-operator/curated-operator-form/controls/manager-address-input.tsx new file mode 100644 index 000000000..6d4e9e443 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/manager-address-input.tsx @@ -0,0 +1,19 @@ +import { type FC } from 'react'; +import { AddressInputHookForm } from 'shared/hook-form/controls'; +import { useCuratedOperatorFormData } from '../context'; +import { OwnerChip } from 'shared/components'; + +export const ManagerAddressInput: FC = () => { + const { address } = useCuratedOperatorFormData(true); + return ( + + Manager Address + + } + currentAddress={address} + /> + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/operator-info-inputs.tsx b/features/create-node-operator/curated-operator-form/controls/operator-info-inputs.tsx new file mode 100644 index 000000000..214a1a110 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/operator-info-inputs.tsx @@ -0,0 +1,46 @@ +import { Text } from '@lidofinance/lido-ui'; +import { type FC } from 'react'; +import { Stack } from 'shared/components'; +import { TextInputHookForm } from 'shared/hook-form/controls'; +const MAX_LENGTH = 64; + +export const OperatorInfoInputs: FC = () => { + return ( + + + + + This name will be publicly visible on-chain. You can update it later. + + + + + + + A short blurb about your operator. This description will be publicly + visible on-chain and can be updated later. + + + + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/reward-address-input.tsx b/features/create-node-operator/curated-operator-form/controls/reward-address-input.tsx new file mode 100644 index 000000000..30f9cb9e5 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/reward-address-input.tsx @@ -0,0 +1,14 @@ +import { type FC } from 'react'; +import { AddressInputHookForm } from 'shared/hook-form/controls'; +import { useCuratedOperatorFormData } from '../context'; + +export const RewardAddressInput: FC = () => { + const { address } = useCuratedOperatorFormData(true); + return ( + + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/step-track.tsx b/features/create-node-operator/curated-operator-form/controls/step-track.tsx new file mode 100644 index 000000000..3f32c5e4b --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/step-track.tsx @@ -0,0 +1,25 @@ +import { Text } from '@lidofinance/lido-ui'; +import { type FC } from 'react'; +import { useWatch } from 'react-hook-form'; +import { Stack, StepIndicator } from 'shared/components'; +import type { CuratedOperatorFormInputType } from '../context/types'; + +export const StepTrack: FC = () => { + const currentStep = useWatch({ + name: 'step', + }); + + return ( + + + Step {currentStep} of 4 + + + + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/steps/step-1.tsx b/features/create-node-operator/curated-operator-form/controls/steps/step-1.tsx new file mode 100644 index 000000000..58ecb5fe8 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/steps/step-1.tsx @@ -0,0 +1,41 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { type FC } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { Stack } from 'shared/components'; +import type { CuratedOperatorFormInputType } from '../../context/types'; +import { useStepValidation } from '../../hooks/use-step-validation'; +import { GateSelector } from '../gate-selector'; + +export const Step1: FC = () => { + const currentStep = useWatch({ + name: 'step', + }); + const { setValue } = useFormContext(); + const canContinue = useStepValidation(1); + + if (currentStep !== 1) return null; + + return ( + + + + Select Sub-Node Operator Type + + + Choose the type you want to create now. You can create additional + Sub-Node Operators with other types later + + + + + + + + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/steps/step-2.tsx b/features/create-node-operator/curated-operator-form/controls/steps/step-2.tsx new file mode 100644 index 000000000..d4b9ecfe5 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/steps/step-2.tsx @@ -0,0 +1,110 @@ +import { ROLES } from '@lidofinance/lido-csm-sdk'; +import { Button, Text } from '@lidofinance/lido-ui'; +import { type FC } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { + IconTooltip, + RoleActionsList, + Stack, + WarningBlock, +} from 'shared/components'; +import type { CuratedOperatorFormInputType } from '../../context/types'; +import { useStepValidation } from '../../hooks/use-step-validation'; +import { ManagerAddressInput } from '../manager-address-input'; +import { RewardAddressInput } from '../reward-address-input'; + +export const Step2: FC = () => { + const currentStep = useWatch({ + name: 'step', + }); + const { setValue } = useFormContext(); + const canContinue = useStepValidation(2); + + if (currentStep !== 2) return null; + + return ( + + + + Specify addresses + + + Manager Address will have the ultimate control over the Node + Operator, while Rewards Address is mainly used to receive + rewards + +
      +
    • + + Rewards Address cannot reset the Manager Address + +
    • +
    • + + Manager Address can change the Rewards Address + +
    • +
    +
    + + + + + + Has the ultimate control over the Node Operator. Must be a multisig.{' '} + + } + /> + + + + + + + Used for receiving rewards. Must be a multisig or smart contract + address.{' '} + + } + /> + + + + + + Setting addresses for the Node Operator is at your own risk. If + you specify an incorrect or incompatible address, you may{' '} + permanently lose access to your Node Operator, bond, and + potential rewards. + + + + + + +
    + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/steps/step-3.tsx b/features/create-node-operator/curated-operator-form/controls/steps/step-3.tsx new file mode 100644 index 000000000..f7f6bbef5 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/steps/step-3.tsx @@ -0,0 +1,44 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { type FC } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { Stack } from 'shared/components'; +import type { CuratedOperatorFormInputType } from '../../context/types'; +import { useStepValidation } from '../../hooks/use-step-validation'; +import { OperatorInfoInputs } from '../operator-info-inputs'; + +export const Step3: FC = () => { + const currentStep = useWatch({ + name: 'step', + }); + const { setValue } = useFormContext(); + const canContinue = useStepValidation(3); + + if (currentStep !== 3) return null; + + return ( + + + Set Node Operator name and description + + + + + + + + + + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/steps/step-4.tsx b/features/create-node-operator/curated-operator-form/controls/steps/step-4.tsx new file mode 100644 index 000000000..a1c6efed7 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/steps/step-4.tsx @@ -0,0 +1,41 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { type FC } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { Stack } from 'shared/components'; +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; +import type { CuratedOperatorFormInputType } from '../../context/types'; +import { VerificationSummary } from '../verification-summary'; + +export const Step4: FC = () => { + const currentStep = useWatch({ + name: 'step', + }); + const { + setValue, + formState: { isSubmitting }, + } = useFormContext(); + + if (currentStep !== 4) return null; + + return ( + + + Confirm Node Operator creation + + + + + + + Create Node Operator + + + ); +}; diff --git a/features/create-node-operator/curated-operator-form/controls/verification-summary.tsx b/features/create-node-operator/curated-operator-form/controls/verification-summary.tsx new file mode 100644 index 000000000..4e2819044 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/controls/verification-summary.tsx @@ -0,0 +1,123 @@ +import { Divider, Text } from '@lidofinance/lido-ui'; +import { useCurveParameters } from 'modules/web3/'; +import { type ComponentPropsWithoutRef, type FC, type ReactNode } from 'react'; +import { useWatch } from 'react-hook-form'; +import { Address } from 'shared/components'; +import { + formatEthKeyIntervals, + formatPercentKeyIntervals, +} from 'shared/components/parameters-list/format'; +import { useCurveMetadata } from 'shared/hooks'; +import styled from 'styled-components'; +import type { CuratedOperatorFormInputType } from '../context/'; +import { useCuratedOperatorFormData } from '../context/'; + +const SummaryRow: FC< + ComponentPropsWithoutRef<'div'> & { label: string; children: ReactNode } +> = ({ label, children, ...rest }) => ( + + + {label} + +
    {children}
    +
    +); + +export const VerificationSummary: FC = () => { + const { availableGates = [] } = useCuratedOperatorFormData(); + const [gateName, rewardAddress, managerAddress, name, description] = useWatch< + CuratedOperatorFormInputType, + ['gateName', 'rewardAddress', 'managerAddress', 'name', 'description'] + >({ + name: [ + 'gateName', + 'rewardAddress', + 'managerAddress', + 'name', + 'description', + ], + }); + + const selectedGate = availableGates.find( + (gate) => gate.gateName === gateName, + ); + + const { data: parameters } = useCurveParameters(selectedGate?.curveId); + const metadata = useCurveMetadata(selectedGate?.curveId); + + return ( + + + {metadata?.name ?? '—'} + + + {name} + + + {description} + + + +
    + + +
    + + + + + + + + + + + + ); +}; + +const ListStyle = styled.div` + display: grid; + grid-template-columns: 1fr minmax(auto, 364px); + column-gap: ${({ theme }) => theme.spaceMap.sm}px; + row-gap: ${({ theme }) => theme.spaceMap.xl}px; + + ${({ theme }) => theme.mediaQueries.lg} { + grid-template-columns: 1fr; + } +`; + +const RowStyle = styled.div` + position: relative; + display: grid; + grid-column: 1 / -1; + grid-template-columns: subgrid; + align-items: start; +`; + +const DividerStyle = styled(Divider)` + grid-column: 1 / -1; +`; + +const ParamList = styled.ul` + margin: 4px 0 0; + padding-left: 16px; + list-style: disc; + color: var(--lido-color-text); + + li { + margin-bottom: 2px; + } +`; + +export const ParamValues: FC<{ items: ReactNode[] }> = ({ items }) => ( + + {items.map((item, i) => ( +
  • + {item} +
  • + ))} +
    +); diff --git a/features/create-node-operator/curated-operator-form/curated-operator-form-info.tsx b/features/create-node-operator/curated-operator-form/curated-operator-form-info.tsx new file mode 100644 index 000000000..02baa9cc1 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/curated-operator-form-info.tsx @@ -0,0 +1,13 @@ +import { DataTable } from '@lidofinance/lido-ui'; +import { useWatch } from 'react-hook-form'; +import type { CuratedOperatorFormInputType } from './context/types'; + +export const CuratedOperatorFormInfo = () => { + const currentStep = useWatch({ + name: 'step', + }); + + if (currentStep !== 4) return null; + + return ; +}; diff --git a/features/create-node-operator/curated-operator-form/curated-operator-form.tsx b/features/create-node-operator/curated-operator-form/curated-operator-form.tsx new file mode 100644 index 000000000..62ef2b284 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/curated-operator-form.tsx @@ -0,0 +1,32 @@ +import { type FC, memo } from 'react'; +import { FormBlock, Stack } from 'shared/components'; +import { Form, FormLoader } from 'shared/hook-form/form-controller'; +import { CuratedOperatorDataProvider } from './context/curated-operator-data-provider'; +import { CuratedOperatorFormProvider } from './context/curated-operator-form-provider'; +import { StepTrack } from './controls/step-track'; +import { Step1 } from './controls/steps/step-1'; +import { Step2 } from './controls/steps/step-2'; +import { Step3 } from './controls/steps/step-3'; +import { Step4 } from './controls/steps/step-4'; +import { CuratedOperatorFormInfo } from './curated-operator-form-info'; + +export const CuratedOperatorForm: FC = memo(() => ( + + + + +
    + + + + + + + +
    + +
    +
    +
    +
    +)); diff --git a/features/create-node-operator/curated-operator-form/custom-address-actions.tsx b/features/create-node-operator/curated-operator-form/custom-address-actions.tsx new file mode 100644 index 000000000..f24181ad8 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/custom-address-actions.tsx @@ -0,0 +1,58 @@ +import { Button } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { useModalActions } from 'providers/modal-provider'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { useNavigate } from 'shared/navigate'; +import { Disconnect } from 'shared/wallet'; +import styled from 'styled-components'; + +type Props = { + availableGatesCount: number; +}; + +export const CuratedOperatorCustomAddressActions: FC = ({ + availableGatesCount, +}) => { + const n = useNavigate(); + const { closeModal } = useModalActions(); + + const handleCreateAnother = async () => { + closeModal(); + void n(PATH.CREATE); + }; + + const showCreateAnother = availableGatesCount > 1; + + return ( + + + To continue, connect with the address you specified as Reward/Manager + Address + {showCreateAnother + ? ' or create a new Node Operator using the currently connected address' + : ''} + . + + closeModal()} fullwidth> + Disconnect wallet + + {showCreateAnother && ( + + )} + + ); +}; + +const Description = styled.p` + text-align: center; + color: var(--lido-color-textSecondary); + margin: 0; +`; diff --git a/features/create-node-operator/curated-operator-form/hooks/index.ts b/features/create-node-operator/curated-operator-form/hooks/index.ts new file mode 100644 index 000000000..73e11d0d2 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/hooks/index.ts @@ -0,0 +1 @@ +export { useTxModalStagesCuratedOperator } from './use-tx-modal-stages-curated-operator'; diff --git a/features/create-node-operator/curated-operator-form/hooks/use-step-validation.ts b/features/create-node-operator/curated-operator-form/hooks/use-step-validation.ts new file mode 100644 index 000000000..015bbdafc --- /dev/null +++ b/features/create-node-operator/curated-operator-form/hooks/use-step-validation.ts @@ -0,0 +1,31 @@ +import { useMemo } from 'react'; +import { useFormState, useWatch } from 'react-hook-form'; +import type { CuratedOperatorFormInputType } from '../context/types'; + +type StepField = keyof CuratedOperatorFormInputType; + +const STEP_FIELDS: Record = { + 1: ['gateName'], + 2: ['managerAddress', 'rewardAddress'], + 3: ['name', 'description'], + 4: [], +}; + +export const useStepValidation = (step: number) => { + const fields = useMemo(() => STEP_FIELDS[step] ?? [], [step]); + const values = useWatch({ name: fields }); + const { errors } = useFormState({ + name: fields, + }); + + return useMemo(() => { + if (fields.length === 0) return true; + + const filled = (values as unknown[]).every( + (v) => v !== undefined && v !== '', + ); + const noErrors = fields.every((f) => !errors[f]); + + return filled && noErrors; + }, [fields, values, errors]); +}; diff --git a/features/create-node-operator/curated-operator-form/hooks/use-tx-modal-stages-curated-operator.tsx b/features/create-node-operator/curated-operator-form/hooks/use-tx-modal-stages-curated-operator.tsx new file mode 100644 index 000000000..110597782 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/hooks/use-tx-modal-stages-curated-operator.tsx @@ -0,0 +1,97 @@ +import { + type NodeOperatorShortInfo, + ROLES, + getNodeOperatorRoles, +} from '@lidofinance/lido-csm-sdk'; +import { useCurveMetadataGetter } from 'shared/hooks'; +import { + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import styled from 'styled-components'; +import { + CuratedOperatorFormInputType, + CuratedOperatorFormNetworkData, +} from '../context/types'; +import { CuratedOperatorCustomAddressActions } from '../custom-address-actions'; +import { CuratedOperatorSuccessActions } from '../success-actions'; + +export const useTxModalStagesCuratedOperator = () => { + const getCurveMetadata = useCurveMetadataGetter(); + + return useTxStages< + CuratedOperatorFormInputType, + CuratedOperatorFormNetworkData, + NodeOperatorShortInfo + >((transitStage, input, data) => { + const selectedGate = data.availableGates.find( + (gate) => gate.gateName === input.gateName, + ); + const metadata = getCurveMetadata(selectedGate?.curveId); + + return { + sign: () => + transitStage( + + Creating operator for {metadata?.name} + + } + />, + ), + pending: (txHash) => + transitStage( + + Creating operator for {metadata?.name} + + } + />, + ), + success: (result, txHash) => { + const roles = result ? getNodeOperatorRoles(result, data.address) : []; + const hasAnyRole = roles.length > 0; + const hasManagerRole = roles.includes(ROLES.MANAGER); + + return transitStage( + + Your Node Operator ID is{' '} + {result.nodeOperatorId.toString()} + + ) : undefined + } + footer={ + hasAnyRole ? ( + + ) : ( + + ) + } + />, + ); + }, + }; + }); +}; + +const WrapperSpan = styled.span` + display: block; + margin-bottom: -${({ theme }) => theme.spaceMap.xl}px; +`; diff --git a/features/create-node-operator/curated-operator-form/index.ts b/features/create-node-operator/curated-operator-form/index.ts new file mode 100644 index 000000000..042ce517f --- /dev/null +++ b/features/create-node-operator/curated-operator-form/index.ts @@ -0,0 +1,3 @@ +export * from './curated-operator-form'; +export * from './curated-operator-form-info'; +export * from './context'; diff --git a/features/create-node-operator/curated-operator-form/success-actions.tsx b/features/create-node-operator/curated-operator-form/success-actions.tsx new file mode 100644 index 000000000..cab57ad78 --- /dev/null +++ b/features/create-node-operator/curated-operator-form/success-actions.tsx @@ -0,0 +1,48 @@ +import { Button } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { useModalActions } from 'providers/modal-provider'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { LocalLink, useNavigate } from 'shared/navigate'; + +type Props = { + availableGatesCount: number; + hasManagerRole: boolean; +}; + +export const CuratedOperatorSuccessActions: FC = ({ + availableGatesCount, + hasManagerRole, +}) => { + const n = useNavigate(); + const { closeModal } = useModalActions(); + + const handleCreateAnother = async () => { + closeModal(); + void n(PATH.CREATE); + }; + + const showCreateAnother = availableGatesCount > 1; + + return ( + + {hasManagerRole && ( + + + + )} + {showCreateAnother && ( + + )} + + ); +}; diff --git a/features/create-node-operator/operator-type-modal/operator-type-modal.tsx b/features/create-node-operator/operator-type-modal/operator-type-modal.tsx new file mode 100644 index 000000000..9868145f3 --- /dev/null +++ b/features/create-node-operator/operator-type-modal/operator-type-modal.tsx @@ -0,0 +1,46 @@ +import { Text } from '@lidofinance/lido-ui'; +import { OPERATOR_TYPES_LINK } from 'consts/external-links'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { getUseModal, ModalComponentType } from 'providers/modal-provider'; +import { Grid, MatomoLink, Stack } from 'shared/components'; +import { StyledModal } from './styles'; +import { TypeCard } from './type-card'; +import { useVisibleTypes } from './use-visible-types'; + +export const OperatorTypeModal: ModalComponentType = ({ open, onClose }) => { + const types = useVisibleTypes(); + + return ( + + + Choose operator type + + + Check out details about{' '} + + operator types and parameters + {' '} + to learn more. + + + } + > + + {types.map((type) => ( + + ))} + + + ); +}; + +export const useOperatorTypeModal = getUseModal(OperatorTypeModal); diff --git a/features/create-node-operator/operator-type-modal/parameters.tsx b/features/create-node-operator/operator-type-modal/parameters.tsx new file mode 100644 index 000000000..11b541699 --- /dev/null +++ b/features/create-node-operator/operator-type-modal/parameters.tsx @@ -0,0 +1,26 @@ +import { Text } from '@lidofinance/lido-ui'; +import { useCurveParameters } from 'modules/web3'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { PARAMETERS } from 'shared/components/parameters-list/parameters'; +import { ParametersValue } from 'shared/components/parameters-list/parameters-value'; + +export const Parameters: FC<{ curveId: bigint }> = ({ curveId }) => { + const { data: parameters } = useCurveParameters(curveId); + + return ( + + {PARAMETERS.slice(0, 2).map(({ title: paramTitle, render }) => { + const values = render(parameters); + return ( + + + {paramTitle}: + + + + ); + })} + + ); +}; diff --git a/features/create-node-operator/operator-type-modal/styles.tsx b/features/create-node-operator/operator-type-modal/styles.tsx new file mode 100644 index 000000000..627afb044 --- /dev/null +++ b/features/create-node-operator/operator-type-modal/styles.tsx @@ -0,0 +1,19 @@ +import { Modal } from '@lidofinance/lido-ui'; +import { StackStyle } from 'shared/components'; +import styled from 'styled-components'; + +export const StyledModal = styled(Modal)<{ $compact?: boolean }>` + & > div { + width: ${({ $compact }) => ($compact ? 640 : 800)}px; + } +`; + +export const OptionCard = styled(StackStyle).attrs({ + $direction: 'column', + $justify: 'space-between', +})` + padding: 16px; + border-radius: 10px; + border: 1px solid var(--lido-color-border); + background-color: var(--lido-color-accentControlBg); +`; diff --git a/features/create-node-operator/operator-type-modal/type-card.tsx b/features/create-node-operator/operator-type-modal/type-card.tsx new file mode 100644 index 000000000..eaee24d57 --- /dev/null +++ b/features/create-node-operator/operator-type-modal/type-card.tsx @@ -0,0 +1,48 @@ +import { Button, Divider, Text } from '@lidofinance/lido-ui'; +import { OPERATOR_TYPE_METADATA } from 'consts'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { useOperatorTypeCurveId } from 'shared/hooks'; +import { CurveBadge } from 'shared/node-operator/curve-badge/curve-badge'; +import { LocalLink } from 'shared/navigate'; +import { Parameters } from './parameters'; +import { OptionCard } from './styles'; +import { VisibleType } from './use-visible-types'; + +export const TypeCard: FC<{ type: VisibleType }> = ({ type }) => { + const metadata = OPERATOR_TYPE_METADATA[type.type]; + const curveId = useOperatorTypeCurveId(type.type); + + return ( + + + + + {metadata.name} + + + {metadata.description} + + + + + {curveId !== undefined && } + + + + + + ); +}; diff --git a/features/create-node-operator/operator-type-modal/use-should-show-type-modal.ts b/features/create-node-operator/operator-type-modal/use-should-show-type-modal.ts new file mode 100644 index 000000000..8e4b0ecb5 --- /dev/null +++ b/features/create-node-operator/operator-type-modal/use-should-show-type-modal.ts @@ -0,0 +1,8 @@ +import { useRequestedOperatorType } from 'shared/hooks'; +import { useVisibleTypes } from './use-visible-types'; + +export const useShouldShowTypeModal = () => { + const types = useVisibleTypes(); + const { isRequested } = useRequestedOperatorType(); + return !isRequested && types.length > 1; +}; diff --git a/features/create-node-operator/operator-type-modal/use-visible-types.ts b/features/create-node-operator/operator-type-modal/use-visible-types.ts new file mode 100644 index 000000000..d7ef2700b --- /dev/null +++ b/features/create-node-operator/operator-type-modal/use-visible-types.ts @@ -0,0 +1,94 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { OPERATOR_TYPE_METADATA } from 'consts'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { PATH } from 'consts/urls'; +import { + useIcsPaused, + useIcsProof, + useIdvtcPaused, + useIdvtcProof, +} from 'modules/web3'; +import { useMemo } from 'react'; +import { getOperatorTypeQuery, useShowFlags } from 'shared/hooks'; + +export type VisibleType = { + type: OPERATOR_TYPE; + href: PATH; + query?: Record; + label: string; + matomoEvent: MATOMO_CLICK_EVENTS_TYPES; + primary: boolean; +}; + +type ProofData = { proof?: unknown; isConsumed?: boolean } | undefined; + +const buildApplyEntry = ( + type: OPERATOR_TYPE, + applyPath: PATH, + applyEvent: MATOMO_CLICK_EVENTS_TYPES, + createEvent: MATOMO_CLICK_EVENTS_TYPES, + proof: ProofData, + paused: boolean | undefined, +): VisibleType | null => { + if (paused || proof?.isConsumed) return null; + const { short } = OPERATOR_TYPE_METADATA[type]; + return proof?.proof + ? { + type, + href: PATH.CREATE, + query: getOperatorTypeQuery(type), + label: `Create ${short} operator`, + matomoEvent: createEvent, + primary: true, + } + : { + type, + href: applyPath, + label: `Apply for ${short}`, + matomoEvent: applyEvent, + primary: false, + }; +}; + +export const useVisibleTypes = (): VisibleType[] => { + const { ICS_APPLY_ENABLED } = useShowFlags(); + const { data: icsProof } = useIcsProof(); + const { data: idvtcProof } = useIdvtcProof(); + const { data: icsPaused } = useIcsPaused(); + const { data: idvtcPaused } = useIdvtcPaused(); + + return useMemo(() => { + if (!ICS_APPLY_ENABLED) return []; + + const ics = buildApplyEntry( + OPERATOR_TYPE.CSM_ICS, + PATH.TYPE_ICS_APPLY, + MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalApplyIcs, + MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalCreateIcs, + icsProof, + icsPaused, + ); + const idvtc = buildApplyEntry( + OPERATOR_TYPE.CSM_IDVTC, + PATH.TYPE_DVT_APPLY, + MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalApplyIdvtc, + MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalCreateIdvtc, + idvtcProof, + idvtcPaused, + ); + + const hasAnyProof = Boolean(icsProof?.proof || idvtcProof?.proof); + const def: VisibleType | null = hasAnyProof + ? null + : { + type: OPERATOR_TYPE.CSM_DEF, + href: PATH.CREATE, + label: 'Join now', + matomoEvent: + MATOMO_CLICK_EVENTS_TYPES.operatorTypeModalJoinPermissionless, + primary: true, + }; + + return [def, ics, idvtc].filter((x): x is VisibleType => x !== null); + }, [ICS_APPLY_ENABLED, icsProof, idvtcProof, icsPaused, idvtcPaused]); +}; diff --git a/features/create-node-operator/other-module-banner/other-module-banner.tsx b/features/create-node-operator/other-module-banner/other-module-banner.tsx index 76ec399b6..66a05da04 100644 --- a/features/create-node-operator/other-module-banner/other-module-banner.tsx +++ b/features/create-node-operator/other-module-banner/other-module-banner.tsx @@ -1,14 +1,20 @@ import { Text } from '@lidofinance/lido-ui'; import { getExternalLinks } from 'consts/external-links'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { useOtherModule } from 'modules/web3'; import { FC } from 'react'; import { MatomoLink } from 'shared/components'; -import { useOperatorInOtherModule } from 'shared/hooks'; import { StyledAccordion } from './styles'; +import { isModuleCSM, moduleMeta } from 'consts'; + +const REPLACEMENTS: Record = { + 'curated-onchain-v1': 'Lido Curated v1', +}; export const OtherModuleBanner: FC = () => { const { operatorsWidget } = getExternalLinks(); - const { data: moduleName } = useOperatorInOtherModule(); + const { data } = useOtherModule(); + const moduleName = (data && REPLACEMENTS[data]) ?? data; if (!moduleName) return null; @@ -22,12 +28,13 @@ export const OtherModuleBanner: FC = () => { } > - To become a Node Operator in CSM, start by uploading your first key - here. + To become a Node Operator in {moduleMeta.shortTitle},{' '} + {isModuleCSM ? 'start by uploading your first key' : 'continue'} here.
    - If you want to upload keys to another module (Curated or Simple DVT), + If you want to upload keys to another module (Curated v1 or Simple DVT), navigate to{' '} diff --git a/features/create-node-operator/share-limit-banner/share-limit-banner.tsx b/features/create-node-operator/share-limit-banner/share-limit-banner.tsx index f6a079c34..2b52b5786 100644 --- a/features/create-node-operator/share-limit-banner/share-limit-banner.tsx +++ b/features/create-node-operator/share-limit-banner/share-limit-banner.tsx @@ -1,7 +1,13 @@ +import { isModuleCM } from 'consts'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { + SHARE_LIMIT_STATUS, + useHasPriorityQueueSpots, + useShareLimit, + useShareLimitStatus, +} from 'modules/web3'; import { FC } from 'react'; import { Banner } from 'shared/components'; -import { SHARE_LIMIT_STATUS, useCSMShareLimitInfo } from 'shared/hooks'; import { LocalLink } from 'shared/navigate'; type Props = { activeLeft: string; queue: string }; @@ -15,7 +21,7 @@ const ReachedBanner: FC = () => ( the near future (possibly for months).
    Read more in the FAQ section @@ -37,7 +43,7 @@ const ExhaustedBanner: FC = ({ activeLeft, queue }) => ( can be active for CSM is constantly changing due to protocol dynamics.
    Read more in the FAQ section @@ -56,7 +62,7 @@ const ApproachingBanner: FC = ({ activeLeft, queue }) => ( can be active for CSM is constantly changing due to protocol dynamics.
    Read more in the FAQ section @@ -65,18 +71,24 @@ const ApproachingBanner: FC = ({ activeLeft, queue }) => ( ); export const ShareLimitBanner: FC = () => { - const { data } = useCSMShareLimitInfo(); + const { data } = useShareLimit(); + const { data: status } = useShareLimitStatus(); + const { data: hasPrioritySpots } = useHasPriorityQueueSpots(); + + if (!data || !status || isModuleCM) { + return null; + } return ( <> - {data?.status === SHARE_LIMIT_STATUS.REACHED ? ( + {status === SHARE_LIMIT_STATUS.REACHED ? ( - ) : data?.status === SHARE_LIMIT_STATUS.EXHAUSTED ? ( + ) : status === SHARE_LIMIT_STATUS.EXHAUSTED && !hasPrioritySpots ? ( - ) : data?.status === SHARE_LIMIT_STATUS.APPROACHING ? ( + ) : status === SHARE_LIMIT_STATUS.APPROACHING ? ( > = ({ - Rewards Address - -
    - + + Rewards Address + {!extendedManagerPermissions && } + +
    - Manager Address - -
    - + + Manager Address + {extendedManagerPermissions && } + +
    - {extendedManagerPermissions && } + {extendedManagerPermissions && } ); @@ -111,7 +114,7 @@ const ExtendedManagerPermissions: FC = () => ( These permissions can only be selected during Node Operator Creation, - and cannot be changed in the future. + and cannot be changed in the future @@ -127,6 +130,10 @@ const ExtendedManagerPermissions: FC = () => ( - + ); + +const StepStyle = styled(StepIndicator)` + margin-top: -12px; // @style +`; diff --git a/features/create-node-operator/submit-keys-form/context/index.ts b/features/create-node-operator/submit-keys-form/context/index.ts index eaf7d5839..ba180a0ca 100644 --- a/features/create-node-operator/submit-keys-form/context/index.ts +++ b/features/create-node-operator/submit-keys-form/context/index.ts @@ -1,2 +1,3 @@ export * from './submit-keys-form-provider'; +export * from './submit-keys-data-provider'; export * from './types'; diff --git a/features/create-node-operator/submit-keys-form/context/submit-keys-data-provider.tsx b/features/create-node-operator/submit-keys-form/context/submit-keys-data-provider.tsx new file mode 100644 index 000000000..5c3a61a64 --- /dev/null +++ b/features/create-node-operator/submit-keys-form/context/submit-keys-data-provider.tsx @@ -0,0 +1,130 @@ +import { + KEY_DEPOSIT_QUEUE_BATCHES, + KEY_ICS_PROOF, + KEY_IDVTC_PROOF, + KEY_SHARE_LIMIT, + KEY_STAKE_LIMIT, + useCurveParameters, + useDappStatus, + useEthereumBalance, + useShareLimit, + useShareLimitStatus, + useSmStatus, + useStakeLimit, + useStethBalance, + useWstethBalance, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { + useCreateCurveId, + useInvalidate, + useKeysAvailable, +} from 'shared/hooks'; +import { type SubmitKeysFormNetworkData } from './types'; + +const useSubmitKeysFormNetworkData: NetworkData< + SubmitKeysFormNetworkData +> = () => { + const { data: status, isPending: isStatusLoading } = useSmStatus(); + + const ethBalanceQuery = useEthereumBalance(); + const stethBalanceQuery = useStethBalance(); + const wstethBalanceQuery = useWstethBalance(); + const shareLimitQuery = useShareLimit(); + const maxStakeEthQuery = useStakeLimit(); + + const ethBalance = ethBalanceQuery.data; + const stethBalance = stethBalanceQuery.data; + const wstethBalance = wstethBalanceQuery.data; + const shareLimit = shareLimitQuery.data; + const maxStakeEth = maxStakeEthQuery.data; + + const isEthBalanceLoading = ethBalanceQuery.isPending; + const isStethBalanceLoading = stethBalanceQuery.isPending; + const isWstethBalanceLoading = wstethBalanceQuery.isPending; + const isShareLimitLoading = shareLimitQuery.isPending; + const isMaxStakeEtherLoading = maxStakeEthQuery.isPending; + + const { address } = useDappStatus(); + + const { data: createData, isPending: isCurveIdPending } = useCreateCurveId(); + const { curveId, proof } = createData ?? {}; + + const { data: curveParameters, isPending: isCurveParametersLoading } = + useCurveParameters(curveId); + + const { data: shareLimitStatus } = useShareLimitStatus(); + + const keysAvailable = useKeysAvailable({ + curveId, + ethBalance, + stethBalance, + wstethBalance, + }); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ + ethBalanceQuery.queryKey, + stethBalanceQuery.queryKey, + wstethBalanceQuery.queryKey, + KEY_SHARE_LIMIT, + KEY_STAKE_LIMIT, + KEY_ICS_PROOF, + KEY_IDVTC_PROOF, + KEY_DEPOSIT_QUEUE_BATCHES, + ]); + }, [ + invalidate, + ethBalanceQuery.queryKey, + stethBalanceQuery.queryKey, + wstethBalanceQuery.queryKey, + ]); + + const isPending = + isStethBalanceLoading || + isWstethBalanceLoading || + isEthBalanceLoading || + isMaxStakeEtherLoading || + isStatusLoading || + isShareLimitLoading || + isCurveIdPending || + isCurveParametersLoading; + + return { + data: { + address, + isPaused: status?.isPaused, + proof: proof?.proof, + stethBalance, + wstethBalance, + ethBalance, + curveId, + curveParameters, + maxStakeEth, + shareLimit, + shareLimitStatus, + keysAvailable, + } as SubmitKeysFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useSubmitKeysFormData = useFormData; + +export const SubmitKeysDataProvider: FC = ({ children }) => { + const networkData = useSubmitKeysFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/create-node-operator/submit-keys-form/context/submit-keys-form-provider.tsx b/features/create-node-operator/submit-keys-form/context/submit-keys-form-provider.tsx index e766ab029..572722bcf 100644 --- a/features/create-node-operator/submit-keys-form/context/submit-keys-form-provider.tsx +++ b/features/create-node-operator/submit-keys-form/context/submit-keys-form-provider.tsx @@ -1,68 +1,36 @@ -import { useModifyContext } from 'providers/modify-provider'; -import { FC, PropsWithChildren, useMemo } from 'react'; +import { FC, PropsWithChildren } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormControllerRetry, - useFormData, - useFormDepositData, + FormControllerProvider, + useFlowSubmit, } from 'shared/hook-form/form-controller'; -import { - SubmitKeysFormNetworkData, - type SubmitKeysFormInputType, -} from './types'; -import { useFormBondAmount } from './use-form-bond-amount'; -import { useGetDefaultValues } from './use-get-default-values'; -import { useSubmitKeysFormNetworkData } from './use-submit-keys-form-network-data'; -import { useSubmitKeysSubmit } from './use-submit-keys-submit'; +import { SubmitKeysUpdater } from './submit-keys-updater'; +import { type SubmitKeysFormInputType } from './types'; +import { useSubmitKeysFlowResolver } from './use-submit-keys-flow'; +import { useSubmitKeysDefaultValues } from './use-submit-keys-default-values'; import { useSubmitKeysValidation } from './use-submit-keys-validation'; -export const useSubmitKeysFormData = useFormData; - export const SubmitKeysFormProvider: FC = ({ children }) => { - const [networkData, revalidate] = useSubmitKeysFormNetworkData(); - const validationResolver = useSubmitKeysValidation(networkData); - - const { referrer } = useModifyContext(); - - const asyncDefaultValues = useGetDefaultValues(networkData, referrer); + const resolver = useSubmitKeysValidation(); + const defaultValues = useSubmitKeysDefaultValues(); const formObject = useForm({ - defaultValues: asyncDefaultValues, - resolver: validationResolver, + defaultValues, + resolver, mode: 'onChange', }); - useFormBondAmount(formObject, networkData); - useFormDepositData(formObject); - - const { retryEvent, retryFire } = useFormControllerRetry(); - - const submitKeys = useSubmitKeysSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - SubmitKeysFormInputType, - SubmitKeysFormNetworkData - > = useMemo( - () => ({ - onSubmit: submitKeys, - retryEvent, - }), - [submitKeys, retryEvent], - ); + const submitter = useFlowSubmit(useSubmitKeysFlowResolver()); return ( - - - {children} - - + + + {children} + ); }; diff --git a/features/create-node-operator/submit-keys-form/context/submit-keys-updater.tsx b/features/create-node-operator/submit-keys-form/context/submit-keys-updater.tsx new file mode 100644 index 000000000..fd29d5895 --- /dev/null +++ b/features/create-node-operator/submit-keys-form/context/submit-keys-updater.tsx @@ -0,0 +1,38 @@ +import { useBondByKeysCount } from 'modules/web3'; +import { FC, useEffect } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { useSubmitKeysFormData } from './submit-keys-data-provider'; +import { SubmitKeysFormInputType } from './types'; + +export const SubmitKeysUpdater: FC = () => { + const [token, depositData] = useWatch< + SubmitKeysFormInputType, + ['token', 'depositData'] + >({ name: ['token', 'depositData'] }); + + const keysCount = depositData?.length ?? 0; + + const { trigger, setValue } = useFormContext(); + + const { curveId } = useSubmitKeysFormData(); + + const { data: bondAmount } = useBondByKeysCount({ + keysCount, + token, + curveId, + }); + + useEffect(() => { + void trigger('bondAmount'); + // trigger are stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [token]); + + useEffect(() => { + setValue('bondAmount', bondAmount, { shouldValidate: true }); + // setValue are stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [bondAmount]); + + return null; +}; diff --git a/features/create-node-operator/submit-keys-form/context/types.ts b/features/create-node-operator/submit-keys-form/context/types.ts index 6391b1aee..3e1369567 100644 --- a/features/create-node-operator/submit-keys-form/context/types.ts +++ b/features/create-node-operator/submit-keys-form/context/types.ts @@ -1,43 +1,36 @@ -import { type TOKENS } from 'consts/tokens'; -import { BigNumber } from 'ethers'; -import { DepositDataInputType } from 'shared/hook-form/form-controller'; -import { KeysAvailable, ShareLimitInfo } from 'shared/hooks'; -import { LoadingRecord, Proof } from 'types'; -import { Address } from 'wagmi'; +import { + CurveParameters, + Proof, + ShareLimitInfo, + ShareLimitStatus, + TOKENS, +} from '@lidofinance/lido-csm-sdk'; +import { DepositDataInputType } from 'shared/hook-form/deposit-data'; +import { KeysAvailable } from 'shared/hooks'; +import { Address } from 'viem'; export type SubmitKeysFormInputType = { token: TOKENS; - bondAmount?: BigNumber; + bondAmount?: bigint; referrer?: Address; - rewardsAddress?: string; - managerAddress?: string; + rewardsAddress?: Address; + managerAddress?: Address; extendedManagerPermissions: boolean; specifyCustomAddresses: boolean; specifyReferrrer: boolean; } & DepositDataInputType; export type SubmitKeysFormNetworkData = { - etherBalance?: BigNumber; - stethBalance?: BigNumber; - wstethBalance?: BigNumber; - eaProof?: Proof; - curveId?: BigNumber; - maxStakeEther?: BigNumber | null; - keysUploadLimit?: number; + address: Address; + ethBalance: bigint; + stethBalance: bigint; + wstethBalance: bigint; + curveId: bigint; + curveParameters: CurveParameters; + maxStakeEth: bigint; + isPaused: boolean; + proof?: Proof; + shareLimit: ShareLimitInfo; + shareLimitStatus: ShareLimitStatus; keysAvailable?: KeysAvailable; - isPaused?: boolean; - shareLimit?: ShareLimitInfo; - blockNumber?: number; - loading: LoadingRecord< - | 'etherBalance' - | 'stethBalance' - | 'wstethBalance' - | 'eaProof' - | 'curveId' - | 'keysUploadLimit' - | 'maxStakeEther' - | 'status' - | 'shareLimit' - | 'blockNumber' - >; }; diff --git a/features/create-node-operator/submit-keys-form/context/use-form-bond-amount.ts b/features/create-node-operator/submit-keys-form/context/use-form-bond-amount.ts deleted file mode 100644 index 0c9a84f5a..000000000 --- a/features/create-node-operator/submit-keys-form/context/use-form-bond-amount.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { UseFormReturn } from 'react-hook-form'; -import { useNodeOperatorFirstKeysBond } from 'shared/hooks'; -import { SubmitKeysFormInputType, SubmitKeysFormNetworkData } from './types'; -import { useEffect } from 'react'; - -export const useFormBondAmount = ( - { watch, setValue, trigger }: UseFormReturn, - { curveId }: SubmitKeysFormNetworkData, -) => { - const [token, depositData] = watch(['token', 'depositData']); - - const { data: bondAmount } = useNodeOperatorFirstKeysBond({ - keysCount: depositData?.length, - token, - curveId, - }); - - useEffect(() => { - void trigger('bondAmount'); - }, [token, trigger]); - - useEffect(() => { - setValue('bondAmount', bondAmount, { shouldValidate: true }); - }, [bondAmount, setValue]); -}; diff --git a/features/create-node-operator/submit-keys-form/context/use-get-default-values.ts b/features/create-node-operator/submit-keys-form/context/use-get-default-values.ts deleted file mode 100644 index bc0cbadbd..000000000 --- a/features/create-node-operator/submit-keys-form/context/use-get-default-values.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { useMemo } from 'react'; -import { getMaxBalanceToken } from 'utils'; -import { Address } from 'wagmi'; -import { SubmitKeysFormInputType, SubmitKeysFormNetworkData } from './types'; -import { useDefaultValues } from 'shared/hooks'; - -export const useGetDefaultValues = ( - { - etherBalance, - stethBalance, - wstethBalance, - loading: { - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - }, - }: SubmitKeysFormNetworkData, - referrer?: Address, -) => { - return useDefaultValues( - useMemo(() => { - if ( - [ - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - ].some(Boolean) - ) { - return undefined; - } - - const token = getMaxBalanceToken({ - etherBalance, - stethBalance, - wstethBalance, - }); - - return { - token, - depositData: [], - rawDepositData: '', - confirmKeysReady: false, - extendedManagerPermissions: false, - specifyCustomAddresses: false, - specifyReferrrer: false, - referrer, - }; - }, [ - etherBalance, - isEtherBalanceLoading, - isStethBalanceLoading, - isWstethBalanceLoading, - referrer, - stethBalance, - wstethBalance, - ]), - ); -}; diff --git a/features/create-node-operator/submit-keys-form/context/use-submit-keys-default-values.ts b/features/create-node-operator/submit-keys-form/context/use-submit-keys-default-values.ts new file mode 100644 index 000000000..17b4eff19 --- /dev/null +++ b/features/create-node-operator/submit-keys-form/context/use-submit-keys-default-values.ts @@ -0,0 +1,27 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { getMaxBalanceToken } from 'modules/web3'; +import { useModifyContext } from 'providers/modify-provider'; +import { useFormDefaultValues } from 'shared/hook-form/form-controller'; +import { SubmitKeysFormInputType, SubmitKeysFormNetworkData } from './types'; + +export const useSubmitKeysDefaultValues = () => { + const { referrer } = useModifyContext(); + + return useFormDefaultValues< + SubmitKeysFormInputType, + SubmitKeysFormNetworkData + >((data) => ({ + token: getMaxBalanceToken({ + [TOKENS.eth]: data.ethBalance, + [TOKENS.steth]: data.stethBalance, + [TOKENS.wsteth]: data.wstethBalance, + }), + depositData: [], + rawDepositData: '', + confirmKeysReady: false, + extendedManagerPermissions: false, + specifyCustomAddresses: false, + specifyReferrrer: false, + referrer, + })); +}; diff --git a/features/create-node-operator/submit-keys-form/context/use-submit-keys-flow.ts b/features/create-node-operator/submit-keys-form/context/use-submit-keys-flow.ts new file mode 100644 index 000000000..8b84cd1d0 --- /dev/null +++ b/features/create-node-operator/submit-keys-form/context/use-submit-keys-flow.ts @@ -0,0 +1,122 @@ +import { + getNodeOperatorRoles, + MODULE_NAME, + OPERATOR_TYPE, +} from '@lidofinance/lido-csm-sdk'; +import { PATH } from 'consts'; +import { useOperatorCustomAddresses } from 'features/starter-pack/banner-operator-custom-addresses'; +import { useAppendOperator, useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useModuleOperatorTypeGetter } from 'shared/hooks'; +import { useNavigate } from 'shared/navigate'; +import invariant from 'tiny-invariant'; +import { useConfirmCustomAddressesModal } from '../hooks/use-confirm-modal'; +import { useTxModalStagesSubmitKeys } from '../hooks/use-tx-modal-stages-submit-keys'; +import { useSubmitKeysFormData } from './submit-keys-data-provider'; +import { SubmitKeysFormInputType, SubmitKeysFormNetworkData } from './types'; + +export type SubmitKeysFlow = + { action: 'cannot-submit' } | ({ action: 'submit-keys' } & Executable); + +export const useSubmitKeysFlowResolver = (): FlowResolver< + SubmitKeysFormInputType, + SubmitKeysFormNetworkData, + SubmitKeysFlow +> => { + const sdk = useSmSDK(MODULE_NAME.CSM); + const getOperatorType = useModuleOperatorTypeGetter(); + const appendNO = useAppendOperator(); + const [, setOperatorCustomAddresses] = useOperatorCustomAddresses(); + const n = useNavigate(); + const confirmCustomAddresses = useConfirmCustomAddressesModal(); + const buildCallback = useTxModalStagesSubmitKeys(); + + return useCallback( + (input, data) => { + if (!sdk) return { action: 'cannot-submit' }; + + const { + referrer, + depositData, + token, + bondAmount: amount, + specifyCustomAddresses, + rewardsAddress, + managerAddress, + extendedManagerPermissions, + } = input; + + return { + action: 'submit-keys' as const, + confirm: async () => + !specifyCustomAddresses || + confirmCustomAddresses({ + managerAddress, + rewardsAddress, + extendedManagerPermissions, + }), + submit: async () => { + invariant(amount !== undefined, 'BondAmount is not defined'); + + const callback = buildCallback(input, data); + + const params = { + token, + amount, + depositData, + rewardsAddress: (specifyCustomAddresses && rewardsAddress) || '', + managerAddress: (specifyCustomAddresses && managerAddress) || '', + extendedManagerPermissions: + specifyCustomAddresses && extendedManagerPermissions, + referrer: referrer || undefined, + callback, + }; + + const type = getOperatorType(data.curveId); + + const { result } = + type === OPERATOR_TYPE.CSM_ICS && data.proof + ? await sdk.icsGate.addNodeOperator({ + ...params, + proof: data.proof, + }) + : type === OPERATOR_TYPE.CSM_IDVTC && data.proof + ? await sdk.idvtcGate.addNodeOperator({ + ...params, + proof: data.proof, + }) + : await sdk.permissionlessGate.addNodeOperator(params); + + if (result) { + const roles = getNodeOperatorRoles(result, data.address); + if (roles.length > 0) { + appendNO(result); + } else { + setOperatorCustomAddresses(result.nodeOperatorId); + void n(PATH.HOME); + } + } + }, + }; + }, + [ + sdk, + getOperatorType, + appendNO, + setOperatorCustomAddresses, + n, + confirmCustomAddresses, + buildCallback, + ], + ); +}; + +export const useSubmitKeysFlow = (): SubmitKeysFlow => { + const resolve = useSubmitKeysFlowResolver(); + const data = useSubmitKeysFormData(true); + return resolve({} as SubmitKeysFormInputType, data); +}; diff --git a/features/create-node-operator/submit-keys-form/context/use-submit-keys-form-network-data.tsx b/features/create-node-operator/submit-keys-form/context/use-submit-keys-form-network-data.tsx deleted file mode 100644 index 3aba60b86..000000000 --- a/features/create-node-operator/submit-keys-form/context/use-submit-keys-form-network-data.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { - useEthereumBalance, - useSTETHBalance, - useWSTETHBalance, -} from '@lido-sdk/react'; -import { STRATEGY_LAZY } from 'consts/swr-strategies'; -import { useCallback, useMemo } from 'react'; -import { - useCsmCurveId, - useCsmEarlyAdoption, - useCsmEarlyAdoptionProofConsumed, - useCsmPaused, - useCSMShareLimitInfo, - useKeysAvailable, - useKeysUploadLimit, - useStakingLimitInfo, -} from 'shared/hooks'; -import { useBlockNumber } from 'wagmi'; -import { type SubmitKeysFormNetworkData } from './types'; - -export const useSubmitKeysFormNetworkData = (): [ - SubmitKeysFormNetworkData, - () => Promise, -] => { - const { data: blockNumber, isLoading: isBlockNumberLoading } = - useBlockNumber(); - - const { - data: etherBalance, - update: updateEtherBalance, - initialLoading: isEtherBalanceLoading, - } = useEthereumBalance(undefined, STRATEGY_LAZY); - const { - data: stethBalance, - update: updateStethBalance, - initialLoading: isStethBalanceLoading, - } = useSTETHBalance(STRATEGY_LAZY); - const { - data: wstethBalance, - update: updateWstethBalance, - initialLoading: isWstethBalanceLoading, - } = useWSTETHBalance(STRATEGY_LAZY); - - const { data: ea, initialLoading: isEaProofLoading } = useCsmEarlyAdoption(); - const eaProof = ea?.proof; - - const { data: curveId, initialLoading: isCurveIdLoading } = - useCsmCurveId(!!eaProof); - - const { mutate: mutateConsumed } = useCsmEarlyAdoptionProofConsumed(); - - const { - data: shareLimit, - initialLoading: isShareLimitLoading, - update: updateShareLimit, - } = useCSMShareLimitInfo(); - - const { - data: maxStakeEther, - update: updateMaxStakeEther, - initialLoading: isMaxStakeEtherLoading, - } = useStakingLimitInfo(); - - const { data: keysUploadLimit, initialLoading: isKeysUploadLimitLoading } = - useKeysUploadLimit(); - - const { data: keysAvailable } = useKeysAvailable({ - curveId, - keysUploadLimit, - etherBalance, - stethBalance, - wstethBalance, - }); - - const { data: status, initialLoading: isStatusLoading } = useCsmPaused(); - - const revalidate = useCallback(async () => { - await Promise.allSettled([ - updateStethBalance(), - updateWstethBalance(), - updateEtherBalance(), - mutateConsumed(true), // @note hack to revalidate without loading state - updateShareLimit(), - updateMaxStakeEther(), - ]); - }, [ - updateStethBalance, - updateWstethBalance, - updateEtherBalance, - mutateConsumed, - updateShareLimit, - updateMaxStakeEther, - ]); - - const loading = useMemo( - () => ({ - isStethBalanceLoading, - isWstethBalanceLoading, - isEtherBalanceLoading, - isEaProofLoading, - isCurveIdLoading, - isKeysUploadLimitLoading, - isMaxStakeEtherLoading, - isBlockNumberLoading, - isStatusLoading, - isShareLimitLoading, - }), - [ - isStethBalanceLoading, - isWstethBalanceLoading, - isEtherBalanceLoading, - isEaProofLoading, - isCurveIdLoading, - isKeysUploadLimitLoading, - isMaxStakeEtherLoading, - isBlockNumberLoading, - isStatusLoading, - isShareLimitLoading, - ], - ); - - return [ - { - blockNumber, - stethBalance, - wstethBalance, - etherBalance, - eaProof, - curveId, - keysUploadLimit, - keysAvailable, - maxStakeEther, - shareLimit, - isPaused: status?.isPaused || status?.isAccountingPaused, - loading, - }, - revalidate, - ]; -}; diff --git a/features/create-node-operator/submit-keys-form/context/use-submit-keys-submit.ts b/features/create-node-operator/submit-keys-form/context/use-submit-keys-submit.ts deleted file mode 100644 index 0a171f812..000000000 --- a/features/create-node-operator/submit-keys-form/context/use-submit-keys-submit.ts +++ /dev/null @@ -1,245 +0,0 @@ -import { TOKENS } from 'consts/tokens'; -import { BigNumber } from 'ethers'; -import { BytesLike } from 'ethers/lib/utils.js'; -import { useNodeOperatorContext } from 'providers/node-operator-provider'; -import { useCallback } from 'react'; -import { - GatherPermitSignatureResult, - useAddressCompare, - useAskHowDidYouLearnCsm, - useCSModuleWeb3, - useKeysCache, - usePermitOrApprove, - useSendTx, -} from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import invariant from 'tiny-invariant'; -import { Proof } from 'types'; -import { - addExtraWei, - addressOrZero, - formatKeys, - getAddedNodeOperator, - runWithTransactionLogger, -} from 'utils'; -import { Address } from 'wagmi'; -import { useConfirmCustomAddressesModal } from '../hooks/use-confirm-modal'; -import { useTxModalStagesSubmitKeys } from '../hooks/use-tx-modal-stages-submit-keys'; -import { SubmitKeysFormInputType, SubmitKeysFormNetworkData } from './types'; - -type SubmitKeysOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type MethodParams = { - bondAmount: BigNumber; - keysCount: number; - publicKeys: BytesLike; - signatures: BytesLike; - rewardsAddress: Address; - managerAddress: Address; - extendedManagerPermissions: boolean; - permit: GatherPermitSignatureResult; - eaProof: Proof; - referrer: Address; -}; - -// this encapsulates eth/steth/wsteth flows -const useSubmitKeysTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async (token: TOKENS, params: MethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - switch (token) { - case TOKENS.ETH: - return { - tx: await CSModuleWeb3.populateTransaction.addNodeOperatorETH( - params.keysCount, - params.publicKeys, - params.signatures, - { - managerAddress: params.managerAddress, - rewardAddress: params.rewardsAddress, - extendedManagerPermissions: params.extendedManagerPermissions, - }, - params.eaProof, - params.referrer, - { - value: params.bondAmount, - }, - ), - txName: 'addNodeOperatorETH', - }; - case TOKENS.STETH: - return { - tx: await CSModuleWeb3.populateTransaction.addNodeOperatorStETH( - params.keysCount, - params.publicKeys, - params.signatures, - { - managerAddress: params.managerAddress, - rewardAddress: params.rewardsAddress, - extendedManagerPermissions: params.extendedManagerPermissions, - }, - params.permit, - params.eaProof, - params.referrer, - ), - txName: 'addNodeOperatorStETH', - }; - case TOKENS.WSTETH: - return { - tx: await CSModuleWeb3.populateTransaction.addNodeOperatorWstETH( - params.keysCount, - params.publicKeys, - params.signatures, - { - managerAddress: params.managerAddress, - rewardAddress: params.rewardsAddress, - extendedManagerPermissions: params.extendedManagerPermissions, - }, - params.permit, - params.eaProof, - params.referrer, - ), - txName: 'addNodeOperatorWstETH', - }; - } - }, - [CSModuleWeb3], - ); -}; - -export const useSubmitKeysSubmit = ({ - onConfirm, - onRetry, -}: SubmitKeysOptions) => { - const { txModalStages } = useTxModalStagesSubmitKeys(); - const { append: appendNO } = useNodeOperatorContext(); - const getTx = useSubmitKeysTx(); - const getPermitOrApprove = usePermitOrApprove(); - const sendTx = useSendTx(); - const isUserOrZero = useAddressCompare(true); - const { addCacheKeys } = useKeysCache(); - - const confirmCustomAddresses = useConfirmCustomAddressesModal(); - const { ask } = useAskHowDidYouLearnCsm(); - - return useCallback( - async ( - { - referrer, - depositData, - token, - bondAmount, - specifyCustomAddresses, - rewardsAddress, - managerAddress, - extendedManagerPermissions, - }: SubmitKeysFormInputType, - { eaProof }: SubmitKeysFormNetworkData, - ): Promise => { - invariant(depositData.length, 'Keys is not defined'); - invariant(token, 'Token is not defined'); - invariant(bondAmount, 'BondAmount is not defined'); - - if ( - specifyCustomAddresses && - !(await confirmCustomAddresses({ - managerAddress, - rewardsAddress, - extendedManagerPermissions, - })) - ) { - return false; - } - - try { - const { permit } = await getPermitOrApprove({ - token, - amount: addExtraWei(bondAmount, token), - txModalStages, - }); - - const { keysCount, publicKeys, signatures } = formatKeys(depositData); - - txModalStages.sign({ keysCount, amount: bondAmount, token }); - - const tx = await getTx(token, { - bondAmount, - keysCount, - publicKeys, - signatures, - permit, - eaProof: eaProof || [], - rewardsAddress: addressOrZero( - specifyCustomAddresses && rewardsAddress, - ), - managerAddress: addressOrZero( - specifyCustomAddresses && managerAddress, - ), - extendedManagerPermissions: - specifyCustomAddresses && extendedManagerPermissions, - referrer: addressOrZero(referrer), - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'AddNodeOperator signing', - () => sendTx(tx), - ); - - txModalStages.pending({ keysCount, amount: bondAmount, token }, txHash); - - const receipt = await runWithTransactionLogger( - 'AddNodeOperator block confirmation', - waitTx, - ); - - const nodeOperator = getAddedNodeOperator(receipt); - - txModalStages.success( - { - nodeOperatorId: nodeOperator?.id, - keys: depositData.map((key) => key.pubkey), - }, - txHash, - ); - ask(); - - // TODO: move to onConfirm - void addCacheKeys(depositData.map(({ pubkey }) => pubkey)); - - // TODO: move to onConfirm - if (nodeOperator) { - appendNO({ - id: nodeOperator.id, - manager: isUserOrZero(nodeOperator.managerAddress), - rewards: isUserOrZero(nodeOperator.rewardsAddress), - }); - } - - await onConfirm?.(); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [ - confirmCustomAddresses, - getPermitOrApprove, - txModalStages, - getTx, - onConfirm, - addCacheKeys, - sendTx, - appendNO, - isUserOrZero, - onRetry, - ask, - ], - ); -}; diff --git a/features/create-node-operator/submit-keys-form/context/use-submit-keys-validation.ts b/features/create-node-operator/submit-keys-form/context/use-submit-keys-validation.ts index c35c49794..4a1a40fa1 100644 --- a/features/create-node-operator/submit-keys-form/context/use-submit-keys-validation.ts +++ b/features/create-node-operator/submit-keys-form/context/use-submit-keys-validation.ts @@ -1,103 +1,101 @@ -import { isAddress } from 'ethers/lib/utils.js'; -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; +import { useFeatureFlags } from 'config/feature-flags'; +import { DISABLE_DEPOSIT_DATA_VALIDATION } from 'config/feature-flags/types'; +import { useSmSDK } from 'modules/web3'; import { - handleResolverValidationError, + useFormValidation, validateBondAmount, validateDepositData, ValidationError, } from 'shared/hook-form/validation'; -import { useAccount, useAwaitNetworkData } from 'shared/hooks'; +import { isAddress } from 'viem'; import type { SubmitKeysFormInputType, SubmitKeysFormNetworkData, } from './types'; -export const useSubmitKeysValidation = ( - networkData: SubmitKeysFormNetworkData, -) => { - const dataPromise = useAwaitNetworkData(networkData); - const { chainId } = useAccount(); +export const useSubmitKeysValidation = () => { + const { depositData: sdk } = useSmSDK(); + const featureFlags = useFeatureFlags(); - return useCallback>( - async (values, _, options) => { - try { - const { - token, - bondAmount, - depositData, - specifyCustomAddresses, - rewardsAddress, - managerAddress, - confirmKeysReady, - } = values; - - const { - stethBalance, - wstethBalance, - etherBalance, - maxStakeEther, - keysUploadLimit, - blockNumber, - } = await dataPromise; + return useFormValidation( + 'token', + async ( + { + token, + bondAmount, + depositData, + rawDepositData, + specifyCustomAddresses, + rewardsAddress, + managerAddress, + confirmKeysReady, + }, + { curveParameters, maxStakeEth, ethBalance, stethBalance, wstethBalance }, + validate, + ) => { + // FIXME: validate on submit that token, bondAmount and depositData.length are defined + await validate(['token', 'bondAmount'], () => validateBondAmount({ token, bondAmount, - maxStakeEther, - etherBalance, + maxStakeEth, + ethBalance, stethBalance, wstethBalance, - }); + }), + ); - if ( - options.names?.includes('depositData') || - options.names?.includes('rawDepositData') - ) + // TODO: validate length is zero + await validate('rawDepositData', () => { + if (rawDepositData) { + const { error } = sdk.parseDepositData(rawDepositData); + if (error) { + throw new ValidationError('rawDepositData', error); + } + } else { + throw new ValidationError('rawDepositData', ''); + } + }); + + // TODO: refactor this validation + await validate(['rawDepositData', 'depositData'], async () => { + if (!featureFlags?.[DISABLE_DEPOSIT_DATA_VALIDATION]) { await validateDepositData({ depositData, - chainId, - keysUploadLimit, - blockNumber, + sdk, + keysLimit: curveParameters?.keysLimit, }); + } + }); - if (options.names?.includes('confirmKeysReady') && !confirmKeysReady) { + await validate('confirmKeysReady', () => { + if (!confirmKeysReady) { throw new ValidationError( 'confirmKeysReady', 'Please confirm that the keys are ready', ); } + }); - if (specifyCustomAddresses) { - if ( - options.names?.includes('rewardsAddress') && - !isAddress(rewardsAddress ?? '') - ) { - throw new ValidationError( - 'rewardsAddress', - 'Specify valid Rewards Address', - ); - } - - if ( - options.names?.includes('managerAddress') && - !isAddress(managerAddress ?? '') - ) { - throw new ValidationError( - 'managerAddress', - 'Specify valid Manager Address', - ); - } + await validate('rewardsAddress', () => { + if (specifyCustomAddresses && !isAddress(rewardsAddress ?? '')) { + throw new ValidationError( + 'rewardsAddress', + 'Specify valid Rewards Address', + ); } + }); - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError(error, 'SubmitKeysForm', 'token'); - } + await validate('managerAddress', () => { + if (specifyCustomAddresses && !isAddress(managerAddress ?? '')) { + throw new ValidationError( + 'managerAddress', + 'Specify valid Manager Address', + ); + } + }); }, - [chainId, dataPromise], + [sdk], ); }; diff --git a/features/create-node-operator/submit-keys-form/controls/amount-input.tsx b/features/create-node-operator/submit-keys-form/controls/amount-input.tsx index bf5417199..50174a0e9 100644 --- a/features/create-node-operator/submit-keys-form/controls/amount-input.tsx +++ b/features/create-node-operator/submit-keys-form/controls/amount-input.tsx @@ -1,7 +1,7 @@ import { useFormState, useWatch } from 'react-hook-form'; import { InputAmount } from 'shared/components/input-amount'; -import { getTokenDisplayName } from 'utils/getTokenDisplayName'; +import { getTokenDisplayName } from 'utils'; import { SubmitKeysFormInputType } from '../context'; export const AmountInput = () => { @@ -13,11 +13,12 @@ export const AmountInput = () => { return ( ); }; diff --git a/features/create-node-operator/submit-keys-form/controls/custom-addresses-section.tsx b/features/create-node-operator/submit-keys-form/controls/custom-addresses-section.tsx index b06f7014a..28f9a28f3 100644 --- a/features/create-node-operator/submit-keys-form/controls/custom-addresses-section.tsx +++ b/features/create-node-operator/submit-keys-form/controls/custom-addresses-section.tsx @@ -5,6 +5,7 @@ import { RewardsAddressInput } from './rewards-address-input'; import { RewardsAddressTypeSelect } from './rewards-address-type-select'; import { OptionalSectionHookForm } from 'shared/hook-form/controls'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { EXTENDED_MODE_LINK } from 'consts/external-links'; export const CustomAddressesSection: FC = () => { return ( @@ -20,7 +21,8 @@ export const CustomAddressesSection: FC = () => { access to your Node Operator, bond, and potential rewards. Please check the{' '} detailed description of this feature @@ -36,9 +38,10 @@ export const CustomAddressesSection: FC = () => {
    It can not be changed later on. Please check the{' '} detailed explanation of the options diff --git a/features/create-node-operator/submit-keys-form/controls/keys-confirm.tsx b/features/create-node-operator/submit-keys-form/controls/keys-confirm.tsx index 2b0ace215..58438c271 100644 --- a/features/create-node-operator/submit-keys-form/controls/keys-confirm.tsx +++ b/features/create-node-operator/submit-keys-form/controls/keys-confirm.tsx @@ -1,29 +1,34 @@ +import { Text } from '@lidofinance/lido-ui'; import { FC } from 'react'; +import { Stack } from 'shared/components'; import { CheckboxHookForm } from 'shared/hook-form/controls'; -import { SHARE_LIMIT_STATUS } from 'shared/hooks'; +import { useDepositDataValid } from 'shared/hook-form/deposit-data'; import { useSubmitKeysFormData } from '../context'; -import { Stack } from 'shared/components'; -import { Text } from '@lidofinance/lido-ui'; +import { SHARE_LIMIT_STATUS } from 'modules/web3'; export const KeysConfirm: FC = () => { - const { shareLimit } = useSubmitKeysFormData(); + const { shareLimitStatus } = useSubmitKeysFormData(); + const isDepositDataValid = useDepositDataValid(); return ( - - + + I confirm that:
    • My nodes are synced, running, and ready for the validator activation
    • - {shareLimit?.status === SHARE_LIMIT_STATUS.APPROACHING && ( + {shareLimitStatus === SHARE_LIMIT_STATUS.APPROACHING && (
    • I understand that the deposit time for my keys can be months or longer because CSM is approaching its stake share limit
    • )} - {shareLimit?.status === SHARE_LIMIT_STATUS.REACHED && ( + {shareLimitStatus === SHARE_LIMIT_STATUS.REACHED && (
    • I understand that my newly uploaded keys are very unlikely to receive deposits in the near future because CSM has reached its diff --git a/features/create-node-operator/submit-keys-form/controls/keys-input.tsx b/features/create-node-operator/submit-keys-form/controls/keys-input.tsx index 95a53ef21..4d25ac57e 100644 --- a/features/create-node-operator/submit-keys-form/controls/keys-input.tsx +++ b/features/create-node-operator/submit-keys-form/controls/keys-input.tsx @@ -1,31 +1,28 @@ -import { ABOUT_DEPOSIT_DATA_LINK } from 'consts/external-links'; +import { isModuleCM } from 'consts'; +import { UPLOAD_DEPOSIT_DATA_LINK } from 'consts/external-links'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { useFormState } from 'react-hook-form'; import { FormTitle, MatomoLink } from 'shared/components'; -import { DepositDataInputHookForm } from 'shared/hook-form/controls'; -import { SubmitKeysFormInputType } from '../context'; +import { DepositDataHookForm } from 'shared/hook-form/controls'; export const KeysInput = () => { - const { errors } = useFormState({ - name: ['depositData', 'rawDepositData'], - }); - const error = errors.rawDepositData?.message || errors.depositData?.message; - return ( <> - Learn more - + isModuleCM ? null : ( + + Learn more + + ) } > Upload deposit data - + + ); }; diff --git a/features/create-node-operator/submit-keys-form/controls/keys-limit-warning.tsx b/features/create-node-operator/submit-keys-form/controls/keys-limit-warning.tsx new file mode 100644 index 000000000..07a2199d0 --- /dev/null +++ b/features/create-node-operator/submit-keys-form/controls/keys-limit-warning.tsx @@ -0,0 +1,14 @@ +import { FC } from 'react'; +import { KeysLimitWarning as KeysLimitWarningBlock } from 'shared/components'; +import { useSubmitKeysFormData } from '../context'; + +export const KeysLimitWarning: FC = () => { + const { curveParameters } = useSubmitKeysFormData(); + + return ( + + ); +}; diff --git a/features/create-node-operator/submit-keys-form/controls/manager-address-input.tsx b/features/create-node-operator/submit-keys-form/controls/manager-address-input.tsx index d79c3ead8..0dfecbb4f 100644 --- a/features/create-node-operator/submit-keys-form/controls/manager-address-input.tsx +++ b/features/create-node-operator/submit-keys-form/controls/manager-address-input.tsx @@ -1,13 +1,20 @@ import { AddressInputHookForm } from 'shared/hook-form/controls'; -import { useAccount } from 'shared/hooks'; +import { SubmitKeysFormInputType, useSubmitKeysFormData } from '../context'; +import { useWatch } from 'react-hook-form'; +import { OwnerChip } from 'shared/components'; export const ManagerAddressInput: React.FC = () => { - const { address } = useAccount(); + const { address } = useSubmitKeysFormData(true); + + const extendedManagerPermissions = useWatch< + SubmitKeysFormInputType, + 'extendedManagerPermissions' + >({ name: 'extendedManagerPermissions' }); return ( Manager Address {extendedManagerPermissions && }} currentAddress={address} /> ); diff --git a/features/create-node-operator/submit-keys-form/controls/referrer-input.tsx b/features/create-node-operator/submit-keys-form/controls/referrer-input.tsx index 91887f3c9..16011d63d 100644 --- a/features/create-node-operator/submit-keys-form/controls/referrer-input.tsx +++ b/features/create-node-operator/submit-keys-form/controls/referrer-input.tsx @@ -17,6 +17,8 @@ export const ReferrerInput: FC = () => { [referrer], ); + if (!referrer) return null; + return ( { - const { address } = useAccount(); + const { address } = useSubmitKeysFormData(true); + + const extendedManagerPermissions = useWatch< + SubmitKeysFormInputType, + 'extendedManagerPermissions' + >({ name: 'extendedManagerPermissions' }); return ( Rewards Address {!extendedManagerPermissions && } + } currentAddress={address} /> ); diff --git a/features/create-node-operator/submit-keys-form/controls/rewards-address-type-select.tsx b/features/create-node-operator/submit-keys-form/controls/rewards-address-type-select.tsx index 1856ecf5b..d4fb8e678 100644 --- a/features/create-node-operator/submit-keys-form/controls/rewards-address-type-select.tsx +++ b/features/create-node-operator/submit-keys-form/controls/rewards-address-type-select.tsx @@ -39,7 +39,7 @@ export const RewardsAddressTypeSelect: FC = () => { By choosing this option you will grant Rewards Address the ultimate control over the Node Operator. Further changes of - addresses will be two-phased (proposal and confirmation) + addresses will be two-phased (proposal and confirmation).
      • Rewards Address can reset the Manager Address
      • @@ -63,7 +63,7 @@ export const RewardsAddressTypeSelect: FC = () => { By choosing this option you will grant Manager Address the ultimate control over the Node Operator, while rewards address - is only used to receive rewards. + is only used to receive rewards
        • Rewards Address cannot reset the Manager Address
        • diff --git a/features/create-node-operator/submit-keys-form/controls/submit-button.tsx b/features/create-node-operator/submit-keys-form/controls/submit-button.tsx index c6f129c1a..1f917d4ac 100644 --- a/features/create-node-operator/submit-keys-form/controls/submit-button.tsx +++ b/features/create-node-operator/submit-keys-form/controls/submit-button.tsx @@ -1,15 +1,21 @@ import { PausedButton, SubmitButtonHookForm } from 'shared/hook-form/controls'; -import { useSubmitKeysFormData } from '../context'; +import { SubmitKeysFormInputType, useSubmitKeysFormData } from '../context'; +import { useWatch } from 'react-hook-form'; export const SubmitButton = () => { const { isPaused } = useSubmitKeysFormData(); + const depositData = useWatch({ + name: 'depositData', + }); if (isPaused) { return ; } + const disabled = !depositData?.length; + return ( - + Create Node Operator ); diff --git a/features/create-node-operator/submit-keys-form/controls/token-select.tsx b/features/create-node-operator/submit-keys-form/controls/token-select.tsx index a7a4b7fa0..27384ed9e 100644 --- a/features/create-node-operator/submit-keys-form/controls/token-select.tsx +++ b/features/create-node-operator/submit-keys-form/controls/token-select.tsx @@ -1,65 +1,74 @@ +import { isModuleCM } from 'consts'; +import { CM_BOND_AMOUNTS_LINK } from 'consts/external-links'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { TOKENS } from 'consts/tokens'; import { PATH } from 'consts/urls'; import { FormTitle, KeysAvailable, + MatomoLink, Stack, TokenAmount, } from 'shared/components'; import { TokenButtonsHookForm } from 'shared/hook-form/controls'; import { LocalLink } from 'shared/navigate'; import { useSubmitKeysFormData } from '../context'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; export const TokenSelect: React.FC = () => { - const { etherBalance, stethBalance, wstethBalance, keysAvailable, loading } = + const { ethBalance, stethBalance, wstethBalance, keysAvailable } = useSubmitKeysFormData(); return ( <> - How bond is calculated - + isModuleCM ? ( + + How bond is calculated + + ) : ( + + How bond is calculated + + ) } > Choose bond token - + - ), - [TOKENS.STETH]: ( + [TOKENS.steth]: ( - + - ), - [TOKENS.WSTETH]: ( + [TOKENS.wsteth]: ( - + - ), }} diff --git a/features/create-node-operator/submit-keys-form/header-operator-type-button.tsx b/features/create-node-operator/submit-keys-form/header-operator-type-button.tsx new file mode 100644 index 000000000..9cd741dba --- /dev/null +++ b/features/create-node-operator/submit-keys-form/header-operator-type-button.tsx @@ -0,0 +1,19 @@ +import { FC } from 'react'; +import { useHeaderCustomActions } from 'shared/layout/header'; +import { TypeButton } from 'shared/node-operator/operator-type'; +import { useSubmitKeysFormData } from './context'; + +/** + * Operator type button that appears in the header on the create node operator page. + * Gets the curve ID from the form data and renders the type badge. + * Uses React Portal to render into the header's custom actions slot. + */ +export const HeaderOperatorTypeButton: FC = () => { + const { curveId, address } = useSubmitKeysFormData(); + + return useHeaderCustomActions( + address && curveId !== undefined ? ( + + ) : null, + ); +}; diff --git a/features/create-node-operator/submit-keys-form/hooks/use-tx-modal-stages-submit-keys.tsx b/features/create-node-operator/submit-keys-form/hooks/use-tx-modal-stages-submit-keys.tsx index 2ea4e96c2..ee7375dfa 100644 --- a/features/create-node-operator/submit-keys-form/hooks/use-tx-modal-stages-submit-keys.tsx +++ b/features/create-node-operator/submit-keys-form/hooks/use-tx-modal-stages-submit-keys.tsx @@ -1,95 +1,97 @@ -import { getGeneralTransactionModalStages } from 'shared/transaction-modal/hooks/get-general-transaction-modal-stages'; import { - TransactionModalTransitStage, - useTransactionModalStage, -} from 'shared/transaction-modal/hooks/use-transaction-modal-stage'; - -import { TOKENS } from 'consts/tokens'; -import type { BigNumber } from 'ethers'; + type NodeOperatorShortInfo, + getNodeOperatorRoles, +} from '@lidofinance/lido-csm-sdk'; import { Plural } from 'shared/components'; -import { AfterKeysUpload, TxAmount } from 'shared/transaction-modal'; import { + AfterCreateCustomNodeOperator, + AfterKeysUpload, + TxAmount, TxStagePending, TxStageSign, TxStageSuccess, -} from 'shared/transaction-modal/tx-stages-basic'; -import { NodeOperatorId } from 'types'; - -type Props = { - keysCount: number; - amount: BigNumber; - token: TOKENS; -}; - -type SuccessProps = { nodeOperatorId?: NodeOperatorId; keys: string[] }; + useTxStages, +} from 'shared/transaction-modal'; +import { + SubmitKeysFormInputType, + SubmitKeysFormNetworkData, +} from '../context/types'; -const getTxModalStagesSubmitKeys = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), +export const useTxModalStagesSubmitKeys = () => + useTxStages< + SubmitKeysFormInputType, + SubmitKeysFormNetworkData, + NodeOperatorShortInfo + >((transitStage, input, data) => { + const keysCount = input.depositData.length; + const amount = input.bondAmount ?? 0n; + const { token } = input; - sign: ({ keysCount, amount, token }: Props) => - transitStage( - - Uploading {keysCount}{' '} - {' '} - {amount && ( + return { + sign: () => + transitStage( + - and depositing + Uploading {keysCount}{' '} + {' '} + {!!amount && ( + <> + and depositing + + )} + . - )} - . - - } - />, - ), - - pending: ({ keysCount, amount, token }: Props, txHash?: string) => - transitStage( - - Uploading {keysCount}{' '} - {' '} - {amount && ( + } + />, + ), + pending: (txHash) => + transitStage( + - and depositing + Uploading {keysCount}{' '} + {' '} + {!!amount && ( + <> + and depositing + + )} + . - )} - . - - } - />, - ), + } + />, + ), + success: (result, txHash) => { + const keys = input.depositData.map((key) => key.pubkey); + const hasAnyRole = result + ? getNodeOperatorRoles(result, data.address).length > 0 + : false; - success: ({ nodeOperatorId, keys }: SuccessProps, txHash?: string) => { - return transitStage( - - Your Node Operator ID is {nodeOperatorId} -
          -
          - - - ) : undefined - } - />, - { - isClosableOnLedger: true, + return transitStage( + + Your Node Operator ID is{' '} + {result.nodeOperatorId.toString()} +
          +
          + {hasAnyRole ? ( + + ) : ( + + )} + + ) : undefined + } + />, + ); }, - ); - }, -}); - -export const useTxModalStagesSubmitKeys = () => { - return useTransactionModalStage(getTxModalStagesSubmitKeys); -}; + }; + }); diff --git a/features/create-node-operator/submit-keys-form/submit-keys-form-info.tsx b/features/create-node-operator/submit-keys-form/submit-keys-form-info.tsx index 48b3275ea..ec0987f61 100644 --- a/features/create-node-operator/submit-keys-form/submit-keys-form-info.tsx +++ b/features/create-node-operator/submit-keys-form/submit-keys-form-info.tsx @@ -7,18 +7,17 @@ export const SubmitKeysFormInfo = () => { name: ['depositData'], }); - const { shareLimit } = useSubmitKeysFormData(); + const { shareLimit } = useSubmitKeysFormData(true); return ( {depositData.length} - {shareLimit?.queue.toString()} + {shareLimit?.queue?.toString()} ); diff --git a/features/create-node-operator/submit-keys-form/submit-keys-form.tsx b/features/create-node-operator/submit-keys-form/submit-keys-form.tsx index 160f21e17..a32d7d40d 100644 --- a/features/create-node-operator/submit-keys-form/submit-keys-form.tsx +++ b/features/create-node-operator/submit-keys-form/submit-keys-form.tsx @@ -2,42 +2,44 @@ import { FC, memo } from 'react'; import { SubmitKeysFormProvider } from './context'; -import { useModifyContext } from 'providers/modify-provider'; +import { DepositQueue } from 'features/view-keys/deposit-queue'; import { FormBlock } from 'shared/components'; -import { - BaseFormLoader, - FormControllerStyled, -} from 'shared/hook-form/form-controller'; +import { Form, FormLoader } from 'shared/hook-form/form-controller'; +import { Gate } from 'shared/navigate'; +import { SubmitKeysDataProvider } from './context'; import { AmountInput } from './controls/amount-input'; import { CustomAddressesSection } from './controls/custom-addresses-section'; +import { KeysConfirm } from './controls/keys-confirm'; import { KeysInput } from './controls/keys-input'; +import { KeysLimitWarning } from './controls/keys-limit-warning'; import { ReferrerInput } from './controls/referrer-input'; import { SubmitButton } from './controls/submit-button'; import { TokenSelect } from './controls/token-select'; +import { HeaderOperatorTypeButton } from './header-operator-type-button'; import { SubmitKeysFormInfo } from './submit-keys-form-info'; -import { KeysConfirm } from './controls/keys-confirm'; -import { DepositQueue } from 'features/view-keys/deposit-queue'; - -export const SubmitKeysForm: FC = memo(() => { - const { referrer } = useModifyContext(); - return ( +export const SubmitKeysForm: FC = memo(() => ( + - - - + + + +
          + - {referrer && } + - + -
          +
          - + + +
          - ); -}); +
          +)); diff --git a/features/dashboard/bond/available-to-claim.tsx b/features/dashboard/bond/available-to-claim.tsx index f6beb05d7..9be1793d7 100644 --- a/features/dashboard/bond/available-to-claim.tsx +++ b/features/dashboard/bond/available-to-claim.tsx @@ -1,49 +1,51 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; import { BOND_EXCESS, BOND_INSUFFICIENT } from 'consts/text'; -import { TOKENS } from 'consts/tokens'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; +import { + getNextDistribution, + useFeeSplits, + useFrameInfo, + useNodeOperatorId, + useOperatorBalance, + useOperatorRewards, +} from 'modules/web3'; import { FC } from 'react'; import { Counter, IconTooltip } from 'shared/components'; -import { - getNextRewardsFrame, - useLastRewardsSlot, - useNodeOperatorBalance, - useNodeOperatorRewards, -} from 'shared/hooks'; -import { useAvailableToClaim } from 'shared/hooks/useAvailableToClaim'; -import { formatDate } from 'utils'; +import { calculateAvailableToClaim } from 'utils'; import { Balance } from './balance'; import { AccordionStyle, RowBody, RowHeader, RowTitle } from './styles'; export const AvailableToClaim: FC = () => { - const id = useNodeOperatorId(); + const nodeOperatorId = useNodeOperatorId(); + + const { data: bond, isPending: isBondLoading } = + useOperatorBalance(nodeOperatorId); - const { data: bond, initialLoading: isBondLoading } = - useNodeOperatorBalance(id); + const { data: rewards, isPending: isRewardsLoading } = + useOperatorRewards(nodeOperatorId); - const { data: rewards, initialLoading: isRewardsLoading } = - useNodeOperatorRewards(id); + const { data: feeSplits } = useFeeSplits(nodeOperatorId); - const { data: rewardsSlot } = useLastRewardsSlot(); - const nextRewardsDate = rewardsSlot?.timestamp - ? formatDate(getNextRewardsFrame(rewardsSlot.timestamp)) - : null; + const { data: nextDistribution } = useFrameInfo(getNextDistribution); - const availableToClaim = useAvailableToClaim({ + const availableToClaim = calculateAvailableToClaim({ bond, rewards, + feeSplits, }); return ( Available to claim - {(bond?.isInsufficient || bond?.locked.gt(0)) && ( + {(bond?.isInsufficient || !!bond?.locked) && ( )} { > Rewards @@ -71,7 +74,7 @@ export const AvailableToClaim: FC = () => { warning sign="minus" title={BOND_INSUFFICIENT} - help="Insufficient bond is the missing amount of stETH required to cover all operator’s keys." + help="Insufficient bond is the missing amount of stETH required to cover all operator’s keys" loading={isBondLoading} amount={bond.delta} /> @@ -79,6 +82,7 @@ export const AvailableToClaim: FC = () => { ) : ( <> @@ -91,7 +95,7 @@ export const AvailableToClaim: FC = () => { /> )} - {bond?.locked.gt(0) && ( + {!!bond?.locked && ( <> { title="Locked bond" loading={isBondLoading} amount={bond.locked} - token={TOKENS.ETH} + token={TOKENS.eth} help="Bond is locked because of an MEV stealing event reported by a dedicated committee. This measure ensures that Node Operators are held accountable for any misbehavior or rule violations." /> diff --git a/features/dashboard/bond/balance.tsx b/features/dashboard/bond/balance.tsx index 4d6be46d6..a681ae508 100644 --- a/features/dashboard/bond/balance.tsx +++ b/features/dashboard/bond/balance.tsx @@ -1,5 +1,4 @@ -import { TOKENS } from 'consts/tokens'; -import { BigNumber } from 'ethers'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; import { FC, ReactNode } from 'react'; import { Sign, SignType, TextBlock } from 'shared/components'; import { FormatPrice, FormatToken } from 'shared/formatters'; @@ -8,13 +7,14 @@ import { useEthUsd } from 'shared/hooks'; type Props = { title?: ReactNode; help?: string; - amount?: BigNumber; + amount?: bigint; token?: TOKENS; description?: ReactNode; sign?: SignType; loading?: boolean; big?: boolean; warning?: boolean; + approx?: boolean; }; export const Balance: FC = ({ @@ -23,6 +23,7 @@ export const Balance: FC = ({ big, sign, description, + approx, ...props }) => { const { usdAmount } = useEthUsd(amount); @@ -30,12 +31,14 @@ export const Balance: FC = ({ return ( } + description={ + description ?? + } align={big ? 'flex-end' : undefined} size={big ? 'sm' : undefined} > {sign && } - + ); }; diff --git a/features/dashboard/bond/bond-balance.tsx b/features/dashboard/bond/bond-balance.tsx index 6e5d64fd9..d79c86f06 100644 --- a/features/dashboard/bond/bond-balance.tsx +++ b/features/dashboard/bond/bond-balance.tsx @@ -1,20 +1,20 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; import { BOND_EXCESS, BOND_INSUFFICIENT } from 'consts/text'; -import { TOKENS } from 'consts/tokens'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; +import { useNodeOperatorId, useOperatorBalance } from 'modules/web3'; import { FC } from 'react'; import { Counter } from 'shared/components'; -import { useNodeOperatorBalance } from 'shared/hooks'; import { Balance } from './balance'; import { AccordionStyle, RowBody, RowHeader, RowTitle } from './styles'; export const BondBalance: FC = () => { const id = useNodeOperatorId(); - const { data: bond, initialLoading: isBondLoading } = - useNodeOperatorBalance(id); + const { data: bond, isPending: isBondLoading } = useOperatorBalance(id); + const totalBond = (bond?.current ?? 0n) - (bond?.debt ?? 0n); return ( @@ -22,16 +22,19 @@ export const BondBalance: FC = () => { {bond?.isInsufficient && } } > { /> {bond?.isInsufficient ? ( - <> - - + ) : ( - <> - - + + )} + {!!bond?.debt && ( + )} diff --git a/features/dashboard/bond/bond-section.tsx b/features/dashboard/bond/bond-section.tsx index 784a9cf9c..6ffafe9ed 100644 --- a/features/dashboard/bond/bond-section.tsx +++ b/features/dashboard/bond/bond-section.tsx @@ -12,6 +12,7 @@ export const BondSection: FC = () => { title="Bond & Rewards" href={PATH.BOND} matomoEvent={MATOMO_CLICK_EVENTS_TYPES.dashboardBondLink} + data-testid="bondRewardsSection" > diff --git a/features/dashboard/bond/last-rewards.tsx b/features/dashboard/bond/last-rewards.tsx index c73eb7e00..838cb9609 100644 --- a/features/dashboard/bond/last-rewards.tsx +++ b/features/dashboard/bond/last-rewards.tsx @@ -6,11 +6,20 @@ import { Text, Tooltip, } from '@lidofinance/lido-ui'; -import { differenceInCalendarDays, fromUnixTime } from 'date-fns'; +import { LIDO_OPERATOR_PORTAL_PERFORMANCE_ORACLE } from 'consts/external-links'; +import { isModuleCM, moduleMeta } from 'consts/module'; +import { + useFrameInfo, + useLastReportTimestamps, + useLastReportTxHash, + useNodeOperatorId, + useOperatorInfo, + useOperatorLastRewards, +} from 'modules/web3'; import { ModalComponentType, useModal } from 'providers/modal-provider'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; import { FC, useCallback } from 'react'; import { + FaqLink, GrayText, Plural, Stack, @@ -19,14 +28,11 @@ import { } from 'shared/components'; import { FaqElement } from 'shared/components/faq/styles'; import { - getNextRewardsFrame, - getPrevRewardsFrame, - useLastOperatorRewards, - useLastRewardsSlot, - useLastRewrdsTx, - useNodeOperatorInfo, -} from 'shared/hooks'; -import { formatDate, formatPercent } from 'utils'; + countCalendarDaysLeft, + formatDate, + formatPercent, + isDayInPast, +} from 'utils'; import { Balance } from './balance'; import { AccordionStyle, @@ -38,50 +44,44 @@ import { } from './styles'; export const LastRewards: FC = () => { - const { data: lastRewards, initialLoading: isLoading } = - useLastOperatorRewards(); - const id = useNodeOperatorId(); - const { data: info } = useNodeOperatorInfo(id); - - const { data: rewardsSlot } = useLastRewardsSlot(); - - const lastRewardsDate = rewardsSlot?.timestamp - ? formatDate(rewardsSlot.timestamp) - : null; - const prevRewardsDate = rewardsSlot?.timestamp - ? formatDate(getPrevRewardsFrame(rewardsSlot.timestamp)) - : null; - const nextRewardsDate = rewardsSlot?.timestamp - ? formatDate(getNextRewardsFrame(rewardsSlot.timestamp)) - : null; - const daysLeft = rewardsSlot?.timestamp - ? differenceInCalendarDays( - fromUnixTime(getNextRewardsFrame(rewardsSlot.timestamp)), - new Date(), - ) - : null; + const { data: info } = useOperatorInfo(id); + const { data: lastRewards, isPending: isLoading } = + useOperatorLastRewards(id); + const { data: rewardsFrame } = useFrameInfo((data) => ({ + lastDistribution: formatDate(data.lastReport), + nextDistribution: formatDate(data.nextReport), + daysLeft: countCalendarDaysLeft(data.nextReport), + isDelayed: isDayInPast(data.nextReport), + })); + const { data: prevDistribution } = useLastReportTimestamps((data) => + formatDate(data?.start), + ); - const showThisSection = lastRewards || (info?.totalDepositedKeys ?? 0) > 0; + const showThisSection = + prevDistribution && (lastRewards || (info?.totalDepositedKeys ?? 0) > 0); - const showWhy = lastRewards && lastRewards.distributed.isZero(); + const showWhy = lastRewards && lastRewards.distributed === 0n; if (!showThisSection) return null; return ( - + Latest rewards distribution - {prevRewardsDate && lastRewardsDate && ( - - Report frame: {prevRewardsDate} — {lastRewardsDate} + {prevDistribution && rewardsFrame && ( + + Report frame: {prevDistribution} —{' '} + {rewardsFrame.lastDistribution} )} { - + Next rewards distribution - {rewardsSlot?.timestamp ? ( - - Report frame: {lastRewardsDate} — {nextRewardsDate} + {rewardsFrame ? ( + + Report frame: {rewardsFrame.lastDistribution} —{' '} + {rewardsFrame.nextDistribution} ) : ( )} - {daysLeft !== null && - (daysLeft < 0 ? ( + {rewardsFrame && + (rewardsFrame.isDelayed ? ( Oracle report is delayed ) : ( - + Expected - {daysLeft === 0 ? ( + {rewardsFrame.daysLeft === 0 ? ( 'Today' ) : ( <> - in {daysLeft}{' '} - + in {rewardsFrame.daysLeft}{' '} + )} @@ -133,48 +137,45 @@ export const LastRewards: FC = () => { }; const LastReportStats: FC = () => { - const { data: lastRewards, initialLoading: isLoading } = - useLastOperatorRewards(); - const { data: txHash, initialLoading: isTxLoading } = useLastRewrdsTx(); + const nodeOperatorId = useNodeOperatorId(); + const { data: lastRewards, isPending: isLoading } = + useOperatorLastRewards(nodeOperatorId); + const { data: txHash, isPending: isTxLoading } = useLastReportTxHash(); return ( - - {!lastRewards || lastRewards.validatorsCount ? ( - <> - {' '} + + {!isModuleCM && + (!lastRewards || lastRewards.validatorsCount ? ( - Threshold: {formatPercent(lastRewards?.threshold)}% - + lastRewards?.threshold ? ( + + + Threshold: {formatPercent(lastRewards?.threshold)} + + + ) : null } help="Number of your keys above the performance threshold in the latest report frame" > {lastRewards?.validatorsOverThresholdCount}{' '} /{lastRewards?.validatorsCount} - - {lastRewards?.stuck ? 'YES' : 'NO'} - - - ) : ( - - - - )} + ) : ( + + + + ))} - - - - - + {txHash && ( + + + + + + )} ); }; @@ -196,33 +197,21 @@ const Why: FC = () => { }; export const WhyModal: ModalComponentType = ({ ...props }) => ( - + -

          There are two main reasons of you getting no reward within a frame:

          +

          There are main reason of you getting no reward within a frame:

          1. - If your validator’s performance was below the threshold within the CSM - Performance Oracle frame (7 days for testnet) the validator does not + If your validator’s performance was below the threshold within the{' '} + {moduleMeta.shortName} Performance Oracle frame the validator does not receive rewards for the given frame. Read more about{' '} - - the CSM Performance Oracle - + {/* TODO: temporary CSM Performance Oracle link; replace with a CM + operator portal link (LIDO_OPERATOR_PORTAL_CM) once CM has one. */} + + the {moduleMeta.shortName} Performance Oracle + .
          2. -
          3. - - Your Node Operator has stuck keys - {' '} - due to not exiting a validator requested for exit timely. -
          diff --git a/features/dashboard/dashboard-page.tsx b/features/dashboard/dashboard-page.tsx index d2f3ffc43..e643dec90 100644 --- a/features/dashboard/dashboard-page.tsx +++ b/features/dashboard/dashboard-page.tsx @@ -1,16 +1,15 @@ import { FC } from 'react'; import { Layout } from 'shared/layout'; import { Dashboard } from './dashboard'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { DashboardSubtitle } from './dashboard-subtitle'; +import { DashboardTitle } from './dashboard-title'; -export const DashboardPage: FC = () => { - return ( - - - - ); -}; +export const DashboardPage: FC = () => ( + } + subtitle={} + pageName="Dashboard" + > + + +); diff --git a/features/dashboard/dashboard-subtitle.tsx b/features/dashboard/dashboard-subtitle.tsx new file mode 100644 index 000000000..324b35e3b --- /dev/null +++ b/features/dashboard/dashboard-subtitle.tsx @@ -0,0 +1,55 @@ +import { Divider, Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts'; +import { isModuleCM } from 'consts/module'; +import { useNodeOperator, useOperatorGroup } from 'modules/web3'; +import { FC } from 'react'; +import { Stack } from 'shared/components/stack/stack'; +import { useCurveMetadata } from 'shared/hooks'; +import { DescriptorId, formatGroupTitle } from 'shared/node-operator'; +import styled from 'styled-components'; +import { TextLocalLink } from 'shared/navigate'; + +import { ReactComponent as ArrowRight } from 'assets/icons/arrow-forward.svg'; + +export const DashboardSubtitle: FC = () => { + if (isModuleCM) return ; + + return <>Dashboard; +}; + +const CmSubtitle: FC = () => { + const { + nodeOperator: { nodeOperatorId, curveId }, + } = useNodeOperator(); + const { data: group } = useOperatorGroup(nodeOperatorId); + const metadata = useCurveMetadata(curveId); + + return ( + + + + + + {metadata?.name} + {group ? ( + <> + + + + {formatGroupTitle(group)} + + + + + ) : null} + + ); +}; + +const DividerStyle = styled(Divider).attrs({ type: 'vertical' })` + opacity: 0.3; +`; diff --git a/features/dashboard/dashboard-title.tsx b/features/dashboard/dashboard-title.tsx new file mode 100644 index 000000000..2555d20d9 --- /dev/null +++ b/features/dashboard/dashboard-title.tsx @@ -0,0 +1,47 @@ +import { Edit } from '@lidofinance/lido-ui'; +import { PATH } from 'consts'; +import { isModuleCM, moduleMeta } from 'consts/module'; +import { useNodeOperator, useOperatorMetadata } from 'modules/web3'; +import { FC } from 'react'; +import { SecondaryLocalLink } from 'shared/navigate'; +import styled from 'styled-components'; + +const ModuleTitle: FC = () => <>{moduleMeta.title}; + +export const DashboardTitle: FC = () => { + if (isModuleCM) return ; + + return ; +}; + +const CmTitle: FC = () => { + const { + nodeOperator: { nodeOperatorId }, + } = useNodeOperator(); + const { data: metadata, isPending } = useOperatorMetadata(nodeOperatorId); + + if (isPending) return ; + + return ( + <> + {metadata?.name} + {!metadata?.ownerEditsRestricted && ( + + + + + + )} + + ); +}; + +const InlineWrapper = styled.span` + display: inline-flex; + margin-left: 4px; + vertical-align: middle; +`; diff --git a/features/dashboard/dashboard.tsx b/features/dashboard/dashboard.tsx index 411a5d94f..7ff6d93dd 100644 --- a/features/dashboard/dashboard.tsx +++ b/features/dashboard/dashboard.tsx @@ -2,15 +2,15 @@ import { FC } from 'react'; import { BondSection } from './bond'; import { KeysSection } from './keys'; import { RolesSection } from './roles'; -import { ExternalSection } from './external'; +import { SurveysCta } from './surveys-cta'; export const Dashboard: FC = () => { return ( <> + - ); }; diff --git a/features/dashboard/external/external-button-link.tsx b/features/dashboard/external/external-button-link.tsx deleted file mode 100644 index 2c7155bdf..000000000 --- a/features/dashboard/external/external-button-link.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { External, Text } from '@lidofinance/lido-ui'; -import { ComponentProps, FC, PropsWithChildren, ReactNode } from 'react'; -import { MatomoLink, Stack } from 'shared/components'; -import { StyledLink } from './styles'; - -type Props = { - title: string; - icon?: ReactNode; -} & Pick, 'href' | 'matomoEvent'>; - -export const ExternalButtonLink: FC> = ({ - href, - matomoEvent, - title, - icon, - children, -}) => ( - - - {icon} - - - {title} - - - - - - {children} - - -); diff --git a/features/dashboard/external/external-section.tsx b/features/dashboard/external/external-section.tsx deleted file mode 100644 index 51724c2c9..000000000 --- a/features/dashboard/external/external-section.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { Accordion, Text } from '@lidofinance/lido-ui'; -import { FC } from 'react'; -import { Stack } from 'shared/components'; -import { ExternalButtonLink } from './external-button-link'; - -import { ReactComponent as BeaconchaIcon } from 'assets/icons/beaconcha.svg'; -import { ReactComponent as RatedIcon } from 'assets/icons/rated.svg'; -import { ReactComponent as EthseerIcon } from 'assets/icons/ethseer.svg'; -import { ReactComponent as LidoIcon } from 'assets/icons/lido.svg'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { - useBeaconchainDashboardLink, - useEthSeerLink, - useFeesMonitoningLink, - useOperatorPortalLink, - useRatedLink, -} from 'shared/hooks'; - -export const ExternalSection: FC = () => { - const beaconchainDashboardLink = useBeaconchainDashboardLink(); - const feesMonitoningLink = useFeesMonitoningLink(); - const operatorPortalLink = useOperatorPortalLink(); - const ratedLink = useRatedLink(); - const ethSeerLink = useEthSeerLink(); - - return ( - - External dashboards - - } - > - - } - href={beaconchainDashboardLink} - matomoEvent={MATOMO_CLICK_EVENTS_TYPES.dashboardExternalBeaconchaLink} - > - Dashboard displays statistics of your validators (up to 20 in free - plan) - - } - href={ratedLink} - matomoEvent={MATOMO_CLICK_EVENTS_TYPES.dashboardExternalRatedLink} - > - Provides effectiveness ratings, APRs and other useful metrics - - {ethSeerLink && ( - } - href={ethSeerLink} - matomoEvent={MATOMO_CLICK_EVENTS_TYPES.dashboardExternalEthSeerLink} - > - Provides real-time statistics of your validators’ performance - - )} - } - href={operatorPortalLink} - matomoEvent={ - MATOMO_CLICK_EVENTS_TYPES.dashboardExternalOperatorsPortalLink - } - > - Shows details about invalid keys - - } - href={feesMonitoningLink} - matomoEvent={ - MATOMO_CLICK_EVENTS_TYPES.dashboardExternalFeesMonitoringLink - } - > - Tracks missed slots and blocks with incorrect fee recipient/MEV relays - - - - ); -}; diff --git a/features/dashboard/external/styles.ts b/features/dashboard/external/styles.ts deleted file mode 100644 index 3c6de73c3..000000000 --- a/features/dashboard/external/styles.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ThemeName } from '@lidofinance/lido-ui'; -import { MatomoLink } from 'shared/components'; -import styled from 'styled-components'; - -export const StyledLink = styled(MatomoLink)` - display: flex; - flex-direction: column; - flex: 1 0 47%; - gap: 12px; - align-items: start; - - border: 1px solid var(--lido-color-border); - border-radius: ${({ theme }) => theme.borderRadiusesMap.lg}px; - padding: 12px; - min-width: 240px; - max-width: calc(50% - 8px); - - ${({ theme }) => theme.mediaQueries.lg} { - max-width: unset; - } - - cursor: pointer; - - :hover { - background-color: ${({ theme }) => - theme.name === ThemeName.light ? '#ebf8ff' : '#24343b'}; - } -`; diff --git a/features/dashboard/keys/csm-keys.tsx b/features/dashboard/keys/csm-keys.tsx new file mode 100644 index 000000000..f87fe2e30 --- /dev/null +++ b/features/dashboard/keys/csm-keys.tsx @@ -0,0 +1,48 @@ +import { KEY_STATUS } from '@lidofinance/lido-csm-sdk'; +import { useNodeOperatorId, useOperatorKeysWithStatus } from 'modules/web3'; +import { FC, useCallback } from 'react'; +import { hasStatus, StatusFilter } from 'utils'; +import { Item } from './item'; +import { Row } from './styles'; + +export const CsmKeys: FC = () => { + const id = useNodeOperatorId(); + const { data: keys } = useOperatorKeysWithStatus(id); + + const keysCountWithStatus = useCallback( + (filter: StatusFilter) => keys?.filter(hasStatus(filter)).length, + [keys], + ); + + return ( + + + + + + + ); +}; diff --git a/features/dashboard/keys/item.tsx b/features/dashboard/keys/item.tsx index fa1336da9..bc7feaa38 100644 --- a/features/dashboard/keys/item.tsx +++ b/features/dashboard/keys/item.tsx @@ -1,20 +1,13 @@ -import { InlineLoader, Tooltip } from '@lidofinance/lido-ui'; +import { InlineLoader } from '@lidofinance/lido-ui'; +import { Tooltip } from 'shared/components'; import { FC, ReactNode } from 'react'; -import { Counter, Stack } from 'shared/components'; -import { - ActionStyled, - BoxStyled, - CountStyled, - ItemStyled, - TitleStyled, -} from './styles'; +import { CountStyled, ItemStyled } from './styles'; type ItemProps = { title: string; - count?: number | string; + count?: number | string | ReactNode; tooltip?: string; - variant?: 'warning' | 'secondary'; - reverse?: boolean; + variant?: 'secondary'; }; export const Item: FC = ({ @@ -22,14 +15,13 @@ export const Item: FC = ({ tooltip, count, variant, - reverse, + ...params }) => { const isEmptyCount = !count || typeof count === 'string'; const secondary = variant === 'secondary' || isEmptyCount; - const warning = variant === 'warning' && !isEmptyCount; const body = ( - + {count === undefined ? : count} @@ -46,21 +38,3 @@ export const Item: FC = ({ } return body; }; - -type ItemActionProps = { - action: ReactNode; - title: string; - count: number; -}; - -export const ItemAction: FC = ({ count, title, action }) => { - return ( - - - - {title} - - {action} - - ); -}; diff --git a/features/dashboard/keys/keys-breakdown/index.ts b/features/dashboard/keys/keys-breakdown/index.ts new file mode 100644 index 000000000..a8e7c4280 --- /dev/null +++ b/features/dashboard/keys/keys-breakdown/index.ts @@ -0,0 +1 @@ +export * from './keys-item'; diff --git a/features/dashboard/keys/keys-breakdown/keys-breakdown.tsx b/features/dashboard/keys/keys-breakdown/keys-breakdown.tsx new file mode 100644 index 000000000..eee30dcc9 --- /dev/null +++ b/features/dashboard/keys/keys-breakdown/keys-breakdown.tsx @@ -0,0 +1,176 @@ +import { KEY_STATUS } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { isModuleCM } from 'consts'; +import { MoreKeysChip } from 'features/group/shared'; +import { + useNodeOperatorId, + useOperatorInfo, + useOperatorStakeSummary, +} from 'modules/web3'; +import { FC, useMemo } from 'react'; +import { Plural, SquaredChip, Stack, StatusComment } from 'shared/components'; +import { computeStakeData } from 'utils'; +import { KeysItem } from './keys-item'; +import { AccordionStyle, Alert, Check } from './styles'; +import { useKeysBreakdown } from './use-keys-breakdown'; + +export const KeysBreakdown: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data } = useKeysBreakdown(nodeOperatorId); + const { data: stakeSummary } = useOperatorStakeSummary(nodeOperatorId); + const { data: info } = useOperatorInfo(nodeOperatorId); + + const moreKeys = useMemo(() => { + const stakeAndKeys = + stakeSummary && info ? computeStakeData(stakeSummary, info) : undefined; + return (stakeAndKeys?.potentialAdditionalKeys ?? 0) > 0; + }, [info, stakeSummary]); + + const hasAnyKey = !!info && info.totalAddedKeys > 0; + const hasWeight = isModuleCM && stakeSummary && stakeSummary.weight > 0; + + return ( + + + Keys Breakdown + + + {hasWeight && } + {hasAnyKey && } + +
          + } + > + + {isModuleCM && !hasWeight ? ( + !!data?.counts.depositable && ( + + ) + ) : ( + + )} + + + + + {!isModuleCM && ( + } + /> + )} + } + /> + } + /> + {!isModuleCM && ( + } + /> + )} + } + /> + } + /> + } + /> + +
          + ); +}; + +const IssuesChip: FC<{ issues?: number }> = ({ issues = 0 }) => ( + 0 ? 'error' : 'success'}> + {issues > 0 ? ( + <> + + + + ) : ( + <> + + No issues + + )} + +); diff --git a/features/dashboard/keys/keys-breakdown/keys-item.tsx b/features/dashboard/keys/keys-breakdown/keys-item.tsx new file mode 100644 index 000000000..caa903bba --- /dev/null +++ b/features/dashboard/keys/keys-breakdown/keys-item.tsx @@ -0,0 +1,45 @@ +import { Tooltip } from 'shared/components'; +import { ComponentPropsWithoutRef, FC, ReactNode } from 'react'; +import { ShortInlineLoader, Stack } from 'shared/components'; +import { TitleStyle, VARIANTS, WrapperStyle } from './styles'; + +type KeysItemProps = ComponentPropsWithoutRef<'div'> & { + title: string; + count: number | undefined; + tooltip?: string; + type?: keyof typeof VARIANTS; + comment?: ReactNode; + ignoreCountZero?: boolean; +}; + +export const KeysItem: FC = ({ + title, + count, + type, + comment, + tooltip, + ignoreCountZero, + ...rest +}) => { + const hasCount = + count === undefined ? undefined : count > 0 || ignoreCountZero; + const variant = hasCount + ? (type ?? 'active') + : type === 'active' + ? type + : undefined; + + return ( + + + + + {title} + + {count === undefined ? : {count}} + + {hasCount ? comment : null} + + + ); +}; diff --git a/features/dashboard/keys/keys-breakdown/styles.ts b/features/dashboard/keys/keys-breakdown/styles.ts new file mode 100644 index 000000000..32c83f08c --- /dev/null +++ b/features/dashboard/keys/keys-breakdown/styles.ts @@ -0,0 +1,71 @@ +import { Accordion, Check as CheckIcon } from '@lidofinance/lido-ui'; +import { StackStyle } from 'shared/components'; +import styled, { css } from 'styled-components'; + +import { ReactComponent as AlertIcon } from 'assets/icons/alert.svg'; + +export const Alert = styled(AlertIcon)` + width: 12px; + height: 12px; +`; + +export const Check = styled(CheckIcon)` + width: 20px; + height: 20px; + margin-inline: -4px; +`; + +export const TitleStyle = styled(StackStyle).attrs({ + $direction: 'row', + $gap: 'xs', + $align: 'center', + $justify: 'space-between', +})` + line-height: 24px; +`; + +export const VARIANTS = { + active: css` + --color: var(--lido-color-text); + `, + warning: css` + --weight: 700; + --color: var(--lido-color-warning); + background: color-mix(in srgb, var(--color) 10%, transparent); + padding-block: ${({ theme }) => theme.spaceMap.sm}px; + `, + error: css` + --weight: 700; + --color: var(--lido-color-error); + background: color-mix(in srgb, var(--color) 10%, transparent); + padding-block: ${({ theme }) => theme.spaceMap.sm}px; + `, +}; + +export const WrapperStyle = styled.div<{ + $variant?: keyof typeof VARIANTS; +}>` + border-radius: ${({ theme }) => theme.borderRadiusesMap.lg}px; + padding-inline: ${({ theme }) => theme.spaceMap.md}px; + + ${({ $variant }) => $variant && VARIANTS[$variant]} + + ${TitleStyle} { + color: var(--color, var(--lido-color-textSecondary)); + font-size: ${({ theme }) => theme.fontSizesMap.xs}px; + font-weight: var(--weight, 400); + + & b { + font-size: ${({ theme }) => theme.fontSizesMap.sm}px; + } + } +`; + +export const AccordionStyle = styled(Accordion)` + margin: 0; + + & > div:first-child, + & > div + div > div { + padding: 12px 0px 0px; + } +`; diff --git a/features/dashboard/keys/keys-breakdown/use-keys-breakdown.ts b/features/dashboard/keys/keys-breakdown/use-keys-breakdown.ts new file mode 100644 index 000000000..71f97eebf --- /dev/null +++ b/features/dashboard/keys/keys-breakdown/use-keys-breakdown.ts @@ -0,0 +1,71 @@ +import { + KEY_STATUS, + KeyWithStatus, + NodeOperatorId, +} from '@lidofinance/lido-csm-sdk'; +import { useOperatorKeysWithStatus } from 'modules/web3'; +import { hasStatus, StatusFilter } from 'utils/has-status'; + +const ISSUE_STATUSES: KEY_STATUS[] = [ + KEY_STATUS.WITH_STRIKES, + KEY_STATUS.UNBONDED, + KEY_STATUS.DUPLICATED, + KEY_STATUS.INVALID, + KEY_STATUS.NON_QUEUED, + KEY_STATUS.UNCHECKED, + KEY_STATUS.EXIT_REQUESTED, +]; + +const STATUS_GROUPS: Record = { + depositable: KEY_STATUS.DEPOSITABLE, + activationPending: KEY_STATUS.ACTIVATION_PENDING, + active: [KEY_STATUS.ACTIVE, KEY_STATUS.EXITING], + exited: KEY_STATUS.WITHDRAWAL_PENDING, + withdrawn: KEY_STATUS.WITHDRAWN, + withStrikes: KEY_STATUS.WITH_STRIKES, + unbonded: KEY_STATUS.UNBONDED, + exitRequested: KEY_STATUS.EXIT_REQUESTED, + nonQueued: KEY_STATUS.NON_QUEUED, + duplicated: KEY_STATUS.DUPLICATED, + invalid: KEY_STATUS.INVALID, + unchecked: KEY_STATUS.UNCHECKED, +}; + +type KeysBreakdownCounts = { + depositable: number; + activationPending: number; + active: number; + exited: number; + withdrawn: number; + withStrikes: number; + unbonded: number; + exitRequested: number; + nonQueued: number; + duplicated: number; + invalid: number; + unchecked: number; +}; + +type KeysBreakdownData = { + counts: KeysBreakdownCounts; + issuesCount: number; +}; + +const selectKeysBreakdown = (keys: KeyWithStatus[]): KeysBreakdownData => { + const counts = Object.fromEntries( + Object.entries(STATUS_GROUPS).map(([key, filter]) => [ + key, + keys.filter(hasStatus(filter)).length, + ]), + ) as KeysBreakdownCounts; + + const issuesCount = ISSUE_STATUSES.filter( + (status) => keys.filter(hasStatus(status)).length > 0, + ).length; + + return { counts, issuesCount }; +}; + +export const useKeysBreakdown = (id: NodeOperatorId | undefined) => { + return useOperatorKeysWithStatus(id, selectKeysBreakdown); +}; diff --git a/features/dashboard/keys/keys-section.tsx b/features/dashboard/keys/keys-section.tsx index de7e26805..12816207e 100644 --- a/features/dashboard/keys/keys-section.tsx +++ b/features/dashboard/keys/keys-section.tsx @@ -1,187 +1,28 @@ import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { isModuleCM } from 'consts/module'; import { PATH } from 'consts/urls'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { FC, useCallback } from 'react'; -import { SectionBlock, Stack, StatusComment } from 'shared/components'; -import { - useKeysTotalLimit, - useKeysWithStatus, - useNodeOperatorInfo, -} from 'shared/hooks'; -import { KEY_STATUS } from 'consts/key-status'; -import { Item, ItemAction } from './item'; -import { AccordionStyle, Row, RowTitle } from './styles'; -import { StatusTitle } from 'shared/components/status-chip/status-chip'; - -const BAD_STATUSES: KEY_STATUS[] = [ - KEY_STATUS.UNBONDED, - KEY_STATUS.STUCK, - KEY_STATUS.DUPLICATED, - KEY_STATUS.INVALID, - KEY_STATUS.NON_QUEUED, - KEY_STATUS.UNCHECKED, - KEY_STATUS.EXIT_REQUESTED, -]; +import { FC } from 'react'; +import { SectionBlock, Stack } from 'shared/components'; +import { CsmKeys } from './csm-keys'; +import { KeysBreakdown } from './keys-breakdown/keys-breakdown'; +import { NoGroupBanner } from './no-group-banner'; +import { StakeAndKeys } from './stake-and-keys'; export const KeysSection: FC = () => { - const id = useNodeOperatorId(); - const { data: info } = useNodeOperatorInfo(id); - const { data: eaTarget } = useKeysTotalLimit(); - - const { data: keys } = useKeysWithStatus(); - - const keysWithStatus = useCallback( - (filter: KEY_STATUS | KEY_STATUS[]) => - keys?.filter(({ statuses }) => - (Array.isArray(filter) ? filter : [filter]).some((st) => - statuses.includes(st), - ), - ).length, - [keys], - ); - - const hasWarnings = !!keysWithStatus(BAD_STATUSES); - - const limit = - info && info.targetLimitMode > 0 ? info.targetLimit : eaTarget || '—'; - const limitTooltip = - info?.targetLimitMode === 1 - ? 'The limit of keys for this Node Operator has been set by the protocol' - : info?.targetLimitMode === 2 - ? 'The limit of keys for this Node Operator has been set due to the existence of stuck keys' - : eaTarget - ? 'Early Adoption period implies the limit for the number of keys per a Node Operator to prevent a quick filling of the module by large operators from Day 1' - : undefined; - return ( - - - + <> + + + + {isModuleCM ? : } + - } - > - - - - - - - - - {keys?.length && ( - Issues with keys found, action required - ) : ( - No issues with keys found - ) - } - > - - {hasWarnings && ( - - {BAD_STATUSES.map((badStatus) => - keysWithStatus(badStatus) ? ( - } - /> - ) : null, - )} - - )} - - - - - - - - - - - - - - - - )} - - + + ); }; diff --git a/features/dashboard/keys/no-group-banner.tsx b/features/dashboard/keys/no-group-banner.tsx new file mode 100644 index 000000000..a24c968aa --- /dev/null +++ b/features/dashboard/keys/no-group-banner.tsx @@ -0,0 +1,36 @@ +import { Text } from '@lidofinance/lido-ui'; +import { isModuleCM } from 'consts'; +import { + useNodeOperatorId, + useOperatorGroupId, + useOperatorWeight, +} from 'modules/web3'; +import { FC } from 'react'; +import { HatBlock, Stack } from 'shared/components'; + +export const NoGroupBanner: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: groupId, isPending: isGroupPending } = + useOperatorGroupId(nodeOperatorId); + const { data: weight, isPending: isWeightPending } = + useOperatorWeight(nodeOperatorId); + + if (!isModuleCM || isGroupPending || isWeightPending) return null; + + if (!!groupId && !!weight) return null; + + return ( + + + + Deposits to this Node Operator are currently paused + + + {!groupId + ? 'Your sub-operator is unable to receive deposits because it has not yet been added to the Node Operator group. Deposits will be enabled once the CMC adds it to the group.' + : 'Your sub-operator is unable to receive deposits because its weight in the Node Operator group is zero. Deposits will be enabled once the CMC updates its weight.'} + + + + ); +}; diff --git a/features/dashboard/keys/stake-and-keys/index.ts b/features/dashboard/keys/stake-and-keys/index.ts new file mode 100644 index 000000000..cf030d98c --- /dev/null +++ b/features/dashboard/keys/stake-and-keys/index.ts @@ -0,0 +1 @@ +export { StakeAndKeys } from './stake-and-keys'; diff --git a/features/dashboard/keys/stake-and-keys/stake-and-keys.tsx b/features/dashboard/keys/stake-and-keys/stake-and-keys.tsx new file mode 100644 index 000000000..ffec9fa80 --- /dev/null +++ b/features/dashboard/keys/stake-and-keys/stake-and-keys.tsx @@ -0,0 +1,35 @@ +import { InlineLoader } from '@lidofinance/lido-ui'; +import { + useNodeOperatorId, + useOperatorInfo, + useOperatorKeysWithStatus, + useOperatorStakeSummary, +} from 'modules/web3'; +import { FC, useMemo } from 'react'; +import { computeStakeData } from 'utils'; +import { StakeStats, KeyLimit, StakeRow } from 'features/group/shared'; + +export const StakeAndKeys: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: stakeSummary } = useOperatorStakeSummary(nodeOperatorId); + const { data: info } = useOperatorInfo(nodeOperatorId); + const { data: keys } = useOperatorKeysWithStatus(nodeOperatorId); + + const data = useMemo(() => { + if (stakeSummary && info) { + return computeStakeData(stakeSummary, info, keys); + } + return undefined; + }, [stakeSummary, info, keys]); + + return data ? ( + <> + + + + ) : ( + + + + ); +}; diff --git a/features/dashboard/keys/styles.ts b/features/dashboard/keys/styles.ts index c10d22e42..b1404ff21 100644 --- a/features/dashboard/keys/styles.ts +++ b/features/dashboard/keys/styles.ts @@ -1,115 +1,40 @@ -import { Accordion } from '@lidofinance/lido-ui'; import { StackStyle } from 'shared/components/stack/style'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; export const Row = styled.div` - border-radius: ${({ theme }) => theme.borderRadiusesMap.md}px; padding: 12px 16px; - display: grid; - grid-auto-flow: column; - grid-auto-columns: 1fr; + display: flex; gap: 12px; - - background: var(--lido-color-backgroundSecondary); - - ${({ theme }) => theme.mediaQueries.lg} { - grid-auto-flow: row; - } `; export const ItemStyled = styled(StackStyle).attrs({ $direction: 'column', $gap: 'xs', -})<{ $secondary?: boolean; $warning?: boolean; $reverse?: boolean }>` - font-size: 14px; +})<{ $secondary?: boolean }>` + display: flex; + flex: 1 0 auto; + font-size: 12px; line-height: 20px; color: var( - ${({ $secondary, $warning }) => - $secondary - ? '--lido-color-textSecondary' - : $warning - ? '--lido-color-error' - : '--lido-color-text'} + ${({ $secondary }) => + $secondary ? '--lido-color-textSecondary' : '--lido-color-text'} ); - text-align: center; + text-align: left; + justify-content: start; - ${({ $reverse }) => - $reverse && - css` - flex-direction: column-reverse; - gap: 0px; - `} + flex-direction: column-reverse; + gap: 0px; ${({ theme }) => theme.mediaQueries.lg} { flex-direction: row-reverse; justify-content: space-between; - - ${({ $reverse }) => - $reverse && - css` - flex-direction: column-reverse; - `} } `; export const CountStyled = styled.b` - font-size: 16px; - font-weight: 700; - line-height: 24px; -`; - -export const RowTitle = styled.h4` - font-size: ${({ theme }) => theme.fontSizesMap.sm}px; - line-height: ${({ theme }) => theme.fontSizesMap.xl}px; - font-weight: 700; - display: flex; - align-items: center; - gap: ${({ theme }) => theme.spaceMap.sm}px; -`; - -export const AccordionStyle = styled(Accordion)<{ $warning?: boolean }>` - --background: ${({ $warning }) => - $warning ? `var(--lido-color-error)` : `var(--lido-color-success)`}; - background: color-mix(in srgb, var(--background) 15%, transparent); - - margin: 0; - - & > div:first-child { - padding: 20px; - } - - & > div + div > div { - padding: 0 20px 20px 20px; - } - - ${Row} { - padding: 0; - background: transparent; - } -`; - -export const ActionStyled = styled.div` - display: grid; - grid-template-columns: 2fr 3fr; - padding: 6px 8px; - align-items: center; - - background: color-mix(in srgb, var(--lido-color-error) 10%, transparent); - border-radius: ${({ theme }) => theme.borderRadiusesMap.md}px; - - ${({ theme }) => theme.mediaQueries.md} { - grid-template-columns: 1fr; - } -`; - -export const BoxStyled = styled.div` - font-size: ${({ theme }) => theme.fontSizesMap.xs}px; - line-height: ${({ theme }) => theme.spaceMap.xl}px; -`; - -export const TitleStyled = styled(BoxStyled)` + font-size: 20px; font-weight: 700; - color: var(--lido-color-text); + line-height: 28px; `; diff --git a/features/dashboard/roles/proposed-address.tsx b/features/dashboard/roles/proposed-address.tsx deleted file mode 100644 index c0863244d..000000000 --- a/features/dashboard/roles/proposed-address.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { FC } from 'react'; -import { Address, Warning } from 'shared/components'; -import { RoleBlockProposed } from './styles'; -import { Text } from '@lidofinance/lido-ui'; - -type Props = { address?: string }; - -export const ProposedAddress: FC = ({ address }) => { - if (!address) return null; - - return ( - - - -
          - - - ); -}; diff --git a/features/dashboard/roles/role-block.tsx b/features/dashboard/roles/role-block.tsx deleted file mode 100644 index 75eddc247..000000000 --- a/features/dashboard/roles/role-block.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { FC } from 'react'; -import { Address, Stack } from 'shared/components'; -import { ProposedAddress } from './proposed-address'; -import { Chip, RoleBlockWrapper, RoleTitle } from './styles'; -import { Text } from '@lidofinance/lido-ui'; - -type RoleBlockProps = { - title: string; - address: string; - proposedAddress?: string; - isYou?: boolean; -}; - -export const RoleBlock: FC = ({ - title, - isYou, - address, - proposedAddress, -}) => { - return ( - - - {title} - {isYou && You} - - -
          - - - - ); -}; diff --git a/features/dashboard/roles/roles-section.tsx b/features/dashboard/roles/roles-section.tsx index 2c4fbf2e4..419ea5c39 100644 --- a/features/dashboard/roles/roles-section.tsx +++ b/features/dashboard/roles/roles-section.tsx @@ -1,38 +1,146 @@ +import { FeeSplit } from '@lidofinance/lido-csm-sdk'; +import { Button, InlineLoader, Text } from '@lidofinance/lido-ui'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; import { PATH } from 'consts/urls'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; +import { + useCustomRewardsClaimer, + useFeeSplits, + useNodeOperatorId, + useOperatorInfo, +} from 'modules/web3'; import { FC } from 'react'; -import { SectionBlock, Stack } from 'shared/components'; -import { useAddressCompare, useNodeOperatorInfo } from 'shared/hooks'; -import { RoleBlock } from './role-block'; +import { + Address, + OwnerChip, + PendingChange, + SectionBlock, + Stack, + YouChip, +} from 'shared/components'; +import { + useCanEditClaimer, + useCanEditSplits, + useShowFlags, +} from 'shared/hooks'; +import { LocalLink } from 'shared/navigate'; +import { zeroAddress } from 'viem'; +import { DividerStyle, RoleRowStyle, RolesGrid } from './styles'; + +const formatShare = (share: bigint) => { + const percent = Number(share) / 100; + return `${percent}%`; +}; export const RolesSection: FC = () => { - const isUserAddress = useAddressCompare(); - const id = useNodeOperatorId(); - const { data: info } = useNodeOperatorInfo(id); + const nodeOperatorId = useNodeOperatorId(); + const { data: info } = useOperatorInfo(nodeOperatorId); + const { data: claimerAddress } = useCustomRewardsClaimer(nodeOperatorId); + const { data: feeSplits } = useFeeSplits(nodeOperatorId); + const { HAS_MANAGER_ROLE, HAS_REWARDS_ROLE } = useShowFlags(); + const canEditClaimer = useCanEditClaimer(); + const canEditSplits = useCanEditSplits(); + + const isClaimerSet = !!claimerAddress && claimerAddress !== zeroAddress; return ( - {info && ( - - - - - )} + + + + Rewards Address + {HAS_REWARDS_ROLE && } + {!info?.extendedManagerPermissions && } + + + {!info ? ( + + ) : ( + <> +
          + {info.proposedRewardsAddress && ( + + )} + + )} + + + + + + + + Manager Address + {HAS_MANAGER_ROLE && } + {!!info?.extendedManagerPermissions && } + + + {!info ? ( + + ) : ( + <> +
          + {info.proposedManagerAddress && ( + + )} + + )} + + + + + + + Rewards claimer + + {isClaimerSet &&
          } + {!isClaimerSet && canEditClaimer && ( + + + + )} + {claimerAddress === zeroAddress && !canEditClaimer && ( + + Not set + + )} + + + + + + + Rewards splitter + + {feeSplits?.map((split: FeeSplit) => ( + +
          + + {formatShare(split.share)} + + + ))} + {!feeSplits?.length && canEditSplits && ( + + + + )} + {feeSplits?.length === 0 && !canEditSplits && ( + + Not set + + )} + + + ); }; diff --git a/features/dashboard/roles/styles.ts b/features/dashboard/roles/styles.ts index ac2c5b894..b0d3772ab 100644 --- a/features/dashboard/roles/styles.ts +++ b/features/dashboard/roles/styles.ts @@ -1,65 +1,23 @@ -import { WarningTextStyle } from 'shared/components/warning/style'; +import { Divider } from '@lidofinance/lido-ui'; +import { Grid } from 'shared/components'; import styled from 'styled-components'; -export const RoleBlockWrapper = styled.div` - display: flex; - flex-direction: column; - flex: 1 0 0; - gap: 12px; - align-items: start; - border: 1px solid var(--lido-color-border); - border-radius: ${({ theme }) => theme.borderRadiusesMap.lg}px; - padding: 12px; - min-width: 240px; -`; +export const RolesGrid = styled(Grid)` + grid-template-columns: 1fr 1fr; -export const RoleBlockProposed = styled.div` - display: flex; - align-self: stretch; - align-items: center; - justify-content: space-between; - background-color: rgba(var(--lido-rgb-warning), 0.1); - border-radius: ${({ theme }) => theme.borderRadiusesMap.xs}px; - padding: ${({ theme }) => theme.spaceMap.xs}px - ${({ theme }) => theme.spaceMap.sm}px; - - ${WarningTextStyle} { - gap: ${({ theme }) => theme.spaceMap.xs}px; - svg { - width: 14px; - height: 14px; - } + ${({ theme }) => theme.mediaQueries.lg} { + grid-template-columns: 1fr; } `; -export const Chip = styled.span` - position: relative; - overflow: hidden; - padding: 0px 6px; - border-radius: ${({ theme }) => theme.borderRadiusesMap.xs}px; - /* background-color:; */ - - align-content: center; - color: var(--lido-color-primary); - font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; - line-height: ${({ theme }) => theme.fontSizesMap.lg}px; - font-weight: 700; - - ::before { - content: ''; - position: absolute; - display: block; - - background-color: var(--lido-color-primary); - transition: opacity 100ms ease 0s; - opacity: 0.1; - inset: 0px; - } +export const RoleRowStyle = styled.div` + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / -1; + align-items: start; + gap: inherit; `; -export const RoleTitle = styled.h4` - color: var(--lido-color-text); - font-size: ${({ theme }) => theme.fontSizesMap.xs}px; - line-height: ${({ theme }) => theme.fontSizesMap.xl}px; - font-weight: 400; +export const DividerStyle = styled(Divider)` + grid-column: 1 / -1; `; diff --git a/features/dashboard/surveys-cta/index.ts b/features/dashboard/surveys-cta/index.ts new file mode 100644 index 000000000..90f421ae2 --- /dev/null +++ b/features/dashboard/surveys-cta/index.ts @@ -0,0 +1 @@ +export * from './surveys-cta'; diff --git a/features/dashboard/surveys-cta/surveys-cta.tsx b/features/dashboard/surveys-cta/surveys-cta.tsx new file mode 100644 index 000000000..984a69a23 --- /dev/null +++ b/features/dashboard/surveys-cta/surveys-cta.tsx @@ -0,0 +1,94 @@ +import { Button } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES, PATH } from 'consts'; +import { FC, useCallback } from 'react'; +import { Banner, CloseButton, InverseThemeProvider } from 'shared/components'; +import { getSurveyDates, useSurveyEnabled } from 'shared/hooks'; +import { LocalLink } from 'shared/navigate'; +import { formatDate, trackMatomoEvent } from 'utils'; + +type SurveysCtaContentProps = { + endDate: Date; +}; + +const SurveysCtaSubmit: FC = ({ endDate }) => ( + <> +
          + Please submit your validator setup data by{' '} + {formatDate(endDate, 'MMMM do')} to help support transparency within the + Lido Protocol. Navigate to the{' '} + + Surveys + {' '} + tab and complete the "Your Setup" form. +
          +
          + + + + + + +); + +const SurveysCtaReview: FC = ({ endDate }) => ( + <> +
          + The configuration of your setup may have changed since your last survey + submission. Please review your setup details by{' '} + {formatDate(endDate, 'MMMM do')}. Navigate to the{' '} + + Surveys + {' '} + tab to proceed. +
          +
          + + + + + + +); + +export const SurveysCta: FC = () => { + const { enabled, variant, onClose } = useSurveyEnabled(); + const { end } = getSurveyDates(); + + const handleClose = useCallback(() => { + trackMatomoEvent(MATOMO_CLICK_EVENTS_TYPES.surveysCtaClose); + onClose(); + }, [onClose]); + + if (!enabled || !variant) return null; + + const isSubmit = variant === 'submit'; + const BannerContent = isSubmit ? SurveysCtaSubmit : SurveysCtaReview; + + return ( + } + > + + + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/context/delayed-penalty-cancel-data-provider.tsx b/features/delayed-penalty/delayed-penalty-cancel-form/context/delayed-penalty-cancel-data-provider.tsx new file mode 100644 index 000000000..03aa4866f --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/context/delayed-penalty-cancel-data-provider.tsx @@ -0,0 +1,57 @@ +import { + KEY_OPERATORS_WITH_LOCKED_BOND, + useEthereumBalance, + useOperatorsCount, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import { type DelayedPenaltyCancelFormNetworkData } from './types'; + +const useDelayedPenaltyCancelFormNetworkData: NetworkData< + DelayedPenaltyCancelFormNetworkData +> = () => { + const ethBalanceQuery = useEthereumBalance(); + + const ethBalance = ethBalanceQuery.data; + const isEthBalanceLoading = ethBalanceQuery.isPending; + + const { data: nodeOperatorsCount, isPending: isNodeOperatorsCountLoading } = + useOperatorsCount(); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ethBalanceQuery.queryKey, KEY_OPERATORS_WITH_LOCKED_BOND]); + }, [invalidate, ethBalanceQuery.queryKey]); + + const isPending = isEthBalanceLoading || isNodeOperatorsCountLoading; + + return { + data: { + ethBalance, + nodeOperatorsCount, + } as DelayedPenaltyCancelFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useDelayedPenaltyCancelFormData = + useFormData; + +export const DelayedPenaltyCancelDataProvider: FC = ({ + children, +}) => { + const networkData = useDelayedPenaltyCancelFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/context/delayed-penalty-cancel-form-provider.tsx b/features/delayed-penalty/delayed-penalty-cancel-form/context/delayed-penalty-cancel-form-provider.tsx new file mode 100644 index 000000000..6a4782adb --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/context/delayed-penalty-cancel-form-provider.tsx @@ -0,0 +1,38 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, +} from 'shared/hook-form/form-controller'; +import { DelayedPenaltyCancelUpdater } from './delayed-penalty-cancel-updater'; +import { type DelayedPenaltyCancelFormInputType } from './types'; +import { useDelayedPenaltyCancelFlowResolver } from './use-delayed-penalty-cancel-flow'; +import { useDelayedPenaltyCancelValidation } from './use-delayed-penalty-cancel-validation'; + +export const DelayedPenaltyCancelFormProvider: FC = ({ + children, +}) => { + const resolver = useDelayedPenaltyCancelValidation(); + + const formObject = useForm({ + defaultValues: { + amount: undefined, + }, + resolver, + mode: 'onChange', + }); + + const submitter = useFlowSubmit(useDelayedPenaltyCancelFlowResolver()); + + return ( + + + + {children} + + + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/context/delayed-penalty-cancel-updater.tsx b/features/delayed-penalty/delayed-penalty-cancel-form/context/delayed-penalty-cancel-updater.tsx new file mode 100644 index 000000000..7197e6056 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/context/delayed-penalty-cancel-updater.tsx @@ -0,0 +1,33 @@ +import { useOperatorBalance } from 'modules/web3'; +import { FC, useEffect } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { DelayedPenaltyCancelFormInputType } from './types'; + +export const DelayedPenaltyCancelUpdater: FC = () => { + const [nodeOperatorId] = useWatch< + DelayedPenaltyCancelFormInputType, + ['nodeOperatorId'] + >({ name: ['nodeOperatorId'] }); + + const { trigger, setValue } = + useFormContext(); + + const { data: maxAmount } = useOperatorBalance( + nodeOperatorId, + (data) => data.locked, + ); + + useEffect(() => { + void trigger('maxAmount'); + // trigger is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [nodeOperatorId]); + + useEffect(() => { + setValue('maxAmount', maxAmount, { shouldValidate: true }); + // setValue is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [maxAmount]); + + return null; +}; diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/context/index.ts b/features/delayed-penalty/delayed-penalty-cancel-form/context/index.ts new file mode 100644 index 000000000..b670748da --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/context/index.ts @@ -0,0 +1,4 @@ +export * from './delayed-penalty-cancel-form-provider'; +export * from './delayed-penalty-cancel-data-provider'; +export * from './types'; +export * from './use-delayed-penalty-cancel-flow'; diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/context/types.ts b/features/delayed-penalty/delayed-penalty-cancel-form/context/types.ts new file mode 100644 index 000000000..6994c58ad --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/context/types.ts @@ -0,0 +1,12 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; + +export type DelayedPenaltyCancelFormInputType = { + amount?: bigint; + nodeOperatorId?: NodeOperatorId; + maxAmount?: bigint; +}; + +export type DelayedPenaltyCancelFormNetworkData = { + ethBalance: bigint; + nodeOperatorsCount: bigint; +}; diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/context/use-delayed-penalty-cancel-flow.ts b/features/delayed-penalty/delayed-penalty-cancel-form/context/use-delayed-penalty-cancel-flow.ts new file mode 100644 index 000000000..9681f4f32 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/context/use-delayed-penalty-cancel-flow.ts @@ -0,0 +1,43 @@ +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import invariant from 'tiny-invariant'; +import { useTxModalStagesDelayedPenaltyCancel } from '../hooks/use-tx-modal-stages-delayed-penalty-cancel'; +import { + DelayedPenaltyCancelFormInputType, + DelayedPenaltyCancelFormNetworkData, +} from './types'; + +export type DelayedPenaltyCancelFlow = { action: 'cancel' } & Executable; + +export const useDelayedPenaltyCancelFlowResolver = (): FlowResolver< + DelayedPenaltyCancelFormInputType, + DelayedPenaltyCancelFormNetworkData, + DelayedPenaltyCancelFlow +> => { + const { delayedPenalty } = useSmSDK(); + const buildCallback = useTxModalStagesDelayedPenaltyCancel(); + + return useCallback( + (input, data) => ({ + action: 'cancel' as const, + submit: () => { + invariant(input.amount !== undefined, 'Amount is not defined'); + invariant( + input.nodeOperatorId !== undefined, + 'NodeOperatorId is not defined', + ); + + return delayedPenalty.cancel({ + nodeOperatorId: input.nodeOperatorId, + amount: input.amount, + callback: buildCallback(input, data), + }); + }, + }), + [delayedPenalty, buildCallback], + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/context/use-delayed-penalty-cancel-validation.ts b/features/delayed-penalty/delayed-penalty-cancel-form/context/use-delayed-penalty-cancel-validation.ts new file mode 100644 index 000000000..aca2ab07f --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/context/use-delayed-penalty-cancel-validation.ts @@ -0,0 +1,47 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { + useFormValidation, + validateBigintMax, + validateEtherAmount, + validateNodeOperatorId, +} from 'shared/hook-form/validation'; +import { getTokenDisplayName } from 'utils'; +import { formatEther } from 'viem'; +import type { + DelayedPenaltyCancelFormInputType, + DelayedPenaltyCancelFormNetworkData, +} from './types'; + +export const useDelayedPenaltyCancelValidation = () => { + return useFormValidation< + DelayedPenaltyCancelFormInputType, + DelayedPenaltyCancelFormNetworkData + >( + 'amount', + async ( + { amount, nodeOperatorId, maxAmount }, + { nodeOperatorsCount }, + validate, + ) => { + await validate('nodeOperatorId', () => { + validateNodeOperatorId( + 'nodeOperatorId', + nodeOperatorId, + nodeOperatorsCount, + ); + }); + + await validate('amount', () => { + validateEtherAmount('amount', amount, TOKENS.eth); + + if (amount && maxAmount) + validateBigintMax( + 'amount', + amount, + maxAmount, + `Entered amount exceeds locked bond of ${formatEther(maxAmount)} ${getTokenDisplayName(TOKENS.eth)}`, + ); + }); + }, + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/controls/amount-input.tsx b/features/delayed-penalty/delayed-penalty-cancel-form/controls/amount-input.tsx new file mode 100644 index 000000000..4969ccf70 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/controls/amount-input.tsx @@ -0,0 +1,22 @@ +import { useWatch } from 'react-hook-form'; +import { FormTitle } from 'shared/components'; +import { TokenAmountInputHookForm } from 'shared/hook-form/controls'; +import { DelayedPenaltyCancelFormInputType } from '../context'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; + +export const AmountInput: React.FC = () => { + const maxAmount = useWatch({ + name: 'maxAmount', + }); + + return ( + <> + Enter cancellation amount + + + ); +}; diff --git a/features/stealing/stealing-cancel-form/controls/node-operator-input.tsx b/features/delayed-penalty/delayed-penalty-cancel-form/controls/node-operator-input.tsx similarity index 100% rename from features/stealing/stealing-cancel-form/controls/node-operator-input.tsx rename to features/delayed-penalty/delayed-penalty-cancel-form/controls/node-operator-input.tsx diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/controls/submit-button.tsx b/features/delayed-penalty/delayed-penalty-cancel-form/controls/submit-button.tsx new file mode 100644 index 000000000..3e4eb1379 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/controls/submit-button.tsx @@ -0,0 +1,5 @@ +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; + +export const SubmitButton = () => { + return Cancel delayed penalty; +}; diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/delayed-penalty-cancel-form.tsx b/features/delayed-penalty/delayed-penalty-cancel-form/delayed-penalty-cancel-form.tsx new file mode 100644 index 000000000..481840a54 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/delayed-penalty-cancel-form.tsx @@ -0,0 +1,30 @@ +import { FC, memo } from 'react'; + +import { + DelayedPenaltyCancelDataProvider, + DelayedPenaltyCancelFormProvider, +} from './context'; + +import { FormBlock } from 'shared/components'; +import { FormLoader, Form } from 'shared/hook-form/form-controller'; +import { AmountInput } from './controls/amount-input'; +import { NodeOperatorInput } from './controls/node-operator-input'; +import { SubmitButton } from './controls/submit-button'; + +export const DelayedPenaltyCancelForm: FC = memo(() => { + return ( + + + + +
          + + + + +
          +
          +
          +
          + ); +}); diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/hooks/use-tx-modal-stages-delayed-penalty-cancel.tsx b/features/delayed-penalty/delayed-penalty-cancel-form/hooks/use-tx-modal-stages-delayed-penalty-cancel.tsx new file mode 100644 index 000000000..f1a3fba7a --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/hooks/use-tx-modal-stages-delayed-penalty-cancel.tsx @@ -0,0 +1,63 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { + TxAmount, + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import { + DelayedPenaltyCancelFormInputType, + DelayedPenaltyCancelFormNetworkData, +} from '../context/types'; + +export const useTxModalStagesDelayedPenaltyCancel = () => + useTxStages< + DelayedPenaltyCancelFormInputType, + DelayedPenaltyCancelFormNetworkData + >((transitStage, input) => ({ + sign: () => + transitStage( + + Node Operator ID: {input.nodeOperatorId?.toString()} +
          + Amount:{' '} + + + } + />, + ), + pending: (txHash) => + transitStage( + + Node Operator ID: {input.nodeOperatorId?.toString()} +
          + Amount:{' '} + + + } + />, + ), + success: (_result: undefined, txHash) => + transitStage( + + Node Operator ID: {input.nodeOperatorId?.toString()} +
          + Amount:{' '} + + + } + />, + ), + })); diff --git a/features/delayed-penalty/delayed-penalty-cancel-form/index.ts b/features/delayed-penalty/delayed-penalty-cancel-form/index.ts new file mode 100644 index 000000000..9779647ee --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-form/index.ts @@ -0,0 +1 @@ +export { DelayedPenaltyCancelForm } from './delayed-penalty-cancel-form'; diff --git a/features/delayed-penalty/delayed-penalty-cancel-page.tsx b/features/delayed-penalty/delayed-penalty-cancel-page.tsx new file mode 100644 index 000000000..617d36c8c --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel-page.tsx @@ -0,0 +1,12 @@ +import { FC } from 'react'; + +import { Layout } from 'shared/layout'; +import { DelayedPenaltyPageSwitcher } from 'shared/navigate'; +import { DelayedPenaltyCancel } from './delayed-penalty-cancel'; + +export const DelayedPenaltyCancelPage: FC = () => ( + + + + +); diff --git a/features/delayed-penalty/delayed-penalty-cancel.tsx b/features/delayed-penalty/delayed-penalty-cancel.tsx new file mode 100644 index 000000000..b1c9571f2 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-cancel.tsx @@ -0,0 +1,17 @@ +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; + +import { DelayedPenaltyCancelForm } from './delayed-penalty-cancel-form'; +import { LockedSection } from './locked-section'; + +export const DelayedPenaltyCancel = () => { + const key = useWeb3Key(); + return ( + <> + + + + + + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-report-form/context/delayed-penalty-report-data-provider.tsx b/features/delayed-penalty/delayed-penalty-report-form/context/delayed-penalty-report-data-provider.tsx new file mode 100644 index 000000000..4976f3018 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/context/delayed-penalty-report-data-provider.tsx @@ -0,0 +1,55 @@ +import { + KEY_OPERATORS_WITH_LOCKED_BOND, + useEthereumBalance, + useOperatorsCount, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import { type DelayedPenaltyReportFormNetworkData } from './types'; + +const useDelayedPenaltyReportFormNetworkData: NetworkData< + DelayedPenaltyReportFormNetworkData +> = () => { + const ethBalanceQuery = useEthereumBalance(); + + const ethBalance = ethBalanceQuery.data; + const isEthBalanceLoading = ethBalanceQuery.isPending; + + const { data: nodeOperatorsCount, isPending: isNodeOperatorsCountLoading } = + useOperatorsCount(); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ethBalanceQuery.queryKey, KEY_OPERATORS_WITH_LOCKED_BOND]); + }, [invalidate, ethBalanceQuery.queryKey]); + + return { + data: { + ethBalance, + nodeOperatorsCount, + } as DelayedPenaltyReportFormNetworkData, + isPending: isEthBalanceLoading || isNodeOperatorsCountLoading, + revalidate, + }; +}; + +export const useDelayedPenaltyReportFormData = + useFormData; + +export const DelayedPenaltyReportDataProvider: FC = ({ + children, +}) => { + const networkData = useDelayedPenaltyReportFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-report-form/context/delayed-penalty-report-form-provider.tsx b/features/delayed-penalty/delayed-penalty-report-form/context/delayed-penalty-report-form-provider.tsx new file mode 100644 index 000000000..a65fd8ef7 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/context/delayed-penalty-report-form-provider.tsx @@ -0,0 +1,36 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, +} from 'shared/hook-form/form-controller'; +import { type DelayedPenaltyReportFormInputType } from './types'; +import { useDelayedPenaltyReportFlowResolver } from './use-delayed-penalty-report-flow'; +import { useDelayedPenaltyReportValidation } from './use-delayed-penalty-report-validation'; + +export const DelayedPenaltyReportFormProvider: FC = ({ + children, +}) => { + const resolver = useDelayedPenaltyReportValidation(); + + const formObject = useForm({ + defaultValues: { + amount: undefined, + }, + resolver, + mode: 'onChange', + }); + + const submitter = useFlowSubmit(useDelayedPenaltyReportFlowResolver()); + + return ( + + + {children} + + + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-report-form/context/index.ts b/features/delayed-penalty/delayed-penalty-report-form/context/index.ts new file mode 100644 index 000000000..cb56891c0 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/context/index.ts @@ -0,0 +1,4 @@ +export * from './delayed-penalty-report-data-provider'; +export * from './delayed-penalty-report-form-provider'; +export * from './types'; +export * from './use-delayed-penalty-report-flow'; diff --git a/features/delayed-penalty/delayed-penalty-report-form/context/types.ts b/features/delayed-penalty/delayed-penalty-report-form/context/types.ts new file mode 100644 index 000000000..7b96edfcb --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/context/types.ts @@ -0,0 +1,13 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; + +export type DelayedPenaltyReportFormInputType = { + amount?: bigint; + nodeOperatorId?: NodeOperatorId; + details?: string; + penaltyType?: number; +}; + +export type DelayedPenaltyReportFormNetworkData = { + ethBalance: bigint; + nodeOperatorsCount: bigint; +}; diff --git a/features/delayed-penalty/delayed-penalty-report-form/context/use-delayed-penalty-report-flow.ts b/features/delayed-penalty/delayed-penalty-report-form/context/use-delayed-penalty-report-flow.ts new file mode 100644 index 000000000..b4e4a6665 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/context/use-delayed-penalty-report-flow.ts @@ -0,0 +1,50 @@ +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import invariant from 'tiny-invariant'; +import { toHex } from 'viem'; +import { useTxModalStagesDelayedPenaltyReport } from '../hooks/use-tx-modal-stages-delayed-penalty-report'; +import { + DelayedPenaltyReportFormInputType, + DelayedPenaltyReportFormNetworkData, +} from './types'; + +export type DelayedPenaltyReportFlow = { action: 'report' } & Executable; + +export const useDelayedPenaltyReportFlowResolver = (): FlowResolver< + DelayedPenaltyReportFormInputType, + DelayedPenaltyReportFormNetworkData, + DelayedPenaltyReportFlow +> => { + const { delayedPenalty } = useSmSDK(); + const buildCallback = useTxModalStagesDelayedPenaltyReport(); + + return useCallback( + (input, data) => ({ + action: 'report' as const, + submit: () => { + invariant(input.amount !== undefined, 'Amount is not defined'); + invariant( + input.nodeOperatorId !== undefined, + 'NodeOperatorId is not defined', + ); + invariant( + input.penaltyType !== undefined && input.penaltyType > 0, + 'PenaltyType is not valid', + ); + + return delayedPenalty.report({ + nodeOperatorId: input.nodeOperatorId, + amount: input.amount, + penaltyType: toHex(BigInt(input.penaltyType), { size: 32 }), + details: input.details || '', + callback: buildCallback(input, data), + }); + }, + }), + [delayedPenalty, buildCallback], + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-report-form/context/use-delayed-penalty-report-validation.ts b/features/delayed-penalty/delayed-penalty-report-form/context/use-delayed-penalty-report-validation.ts new file mode 100644 index 000000000..85b650b37 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/context/use-delayed-penalty-report-validation.ts @@ -0,0 +1,55 @@ +import { maxUint256 } from 'viem'; +import { + useFormValidation, + validateLength, + validateNodeOperatorId, + ValidationError, +} from 'shared/hook-form/validation'; +import type { + DelayedPenaltyReportFormInputType, + DelayedPenaltyReportFormNetworkData, +} from './types'; + +export const useDelayedPenaltyReportValidation = () => { + return useFormValidation< + DelayedPenaltyReportFormInputType, + DelayedPenaltyReportFormNetworkData + >( + 'amount', + async ( + { amount, nodeOperatorId, penaltyType, details }, + { nodeOperatorsCount }, + validate, + ) => { + await validate('nodeOperatorId', () => { + validateNodeOperatorId( + 'nodeOperatorId', + nodeOperatorId, + nodeOperatorsCount, + ); + }); + + await validate('amount', () => { + if (amount === undefined) throw new ValidationError('amount', ''); + if (amount <= 0n) + throw new ValidationError('amount', 'Enter amount greater than 0'); + if (amount > maxUint256) + throw new ValidationError('amount', 'Amount is not valid'); + }); + + await validate('penaltyType', () => { + if (penaltyType === undefined || penaltyType === null) + throw new ValidationError('penaltyType', ''); + if (!Number.isInteger(penaltyType) || penaltyType <= 0) + throw new ValidationError( + 'penaltyType', + 'Enter penalty type greater than 0', + ); + }); + + await validate('details', () => { + validateLength('details', details, 0, 256); + }); + }, + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-report-form/controls/amount-input.tsx b/features/delayed-penalty/delayed-penalty-report-form/controls/amount-input.tsx new file mode 100644 index 000000000..81dae9d45 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/controls/amount-input.tsx @@ -0,0 +1,12 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { FormTitle } from 'shared/components'; +import { TokenAmountInputHookForm } from 'shared/hook-form/controls'; + +export const AmountInput: React.FC = () => { + return ( + <> + Enter penalty amount + + + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-report-form/controls/details-input.tsx b/features/delayed-penalty/delayed-penalty-report-form/controls/details-input.tsx new file mode 100644 index 000000000..b28d8d05b --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/controls/details-input.tsx @@ -0,0 +1,11 @@ +import { FormTitle } from 'shared/components'; +import { TextInputHookForm } from 'shared/hook-form/controls'; + +export const DetailsInput: React.FC = () => { + return ( + <> + Enter Details + + + ); +}; diff --git a/features/stealing/stealing-report-form/controls/node-operator-input.tsx b/features/delayed-penalty/delayed-penalty-report-form/controls/node-operator-input.tsx similarity index 100% rename from features/stealing/stealing-report-form/controls/node-operator-input.tsx rename to features/delayed-penalty/delayed-penalty-report-form/controls/node-operator-input.tsx diff --git a/features/delayed-penalty/delayed-penalty-report-form/controls/penalty-type-input.tsx b/features/delayed-penalty/delayed-penalty-report-form/controls/penalty-type-input.tsx new file mode 100644 index 000000000..fa92d55a5 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/controls/penalty-type-input.tsx @@ -0,0 +1,11 @@ +import { FormTitle } from 'shared/components'; +import { NumberInputHookForm } from 'shared/hook-form/controls'; + +export const PenaltyTypeInput: React.FC = () => { + return ( + <> + Enter Penalty Type + + + ); +}; diff --git a/features/delayed-penalty/delayed-penalty-report-form/controls/submit-button.tsx b/features/delayed-penalty/delayed-penalty-report-form/controls/submit-button.tsx new file mode 100644 index 000000000..6f8e3fd72 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/controls/submit-button.tsx @@ -0,0 +1,5 @@ +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; + +export const SubmitButton = () => { + return Report delayed penalty; +}; diff --git a/features/delayed-penalty/delayed-penalty-report-form/delayed-penalty-report-form.tsx b/features/delayed-penalty/delayed-penalty-report-form/delayed-penalty-report-form.tsx new file mode 100644 index 000000000..bee2a8f58 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/delayed-penalty-report-form.tsx @@ -0,0 +1,32 @@ +import { FC, memo } from 'react'; +import { FormBlock } from 'shared/components'; +import { Form, FormLoader } from 'shared/hook-form/form-controller'; +import { + DelayedPenaltyReportDataProvider, + DelayedPenaltyReportFormProvider, +} from './context'; +import { AmountInput } from './controls/amount-input'; +import { DetailsInput } from './controls/details-input'; +import { NodeOperatorInput } from './controls/node-operator-input'; +import { PenaltyTypeInput } from './controls/penalty-type-input'; +import { SubmitButton } from './controls/submit-button'; + +export const DelayedPenaltyReportForm: FC = memo(() => { + return ( + + + + +
          + + + + + + +
          +
          +
          +
          + ); +}); diff --git a/features/delayed-penalty/delayed-penalty-report-form/hooks/use-tx-modal-stages-delayed-penalty-report.tsx b/features/delayed-penalty/delayed-penalty-report-form/hooks/use-tx-modal-stages-delayed-penalty-report.tsx new file mode 100644 index 000000000..b8f185f4b --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/hooks/use-tx-modal-stages-delayed-penalty-report.tsx @@ -0,0 +1,63 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { + TxAmount, + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import { + DelayedPenaltyReportFormInputType, + DelayedPenaltyReportFormNetworkData, +} from '../context/types'; + +export const useTxModalStagesDelayedPenaltyReport = () => + useTxStages< + DelayedPenaltyReportFormInputType, + DelayedPenaltyReportFormNetworkData + >((transitStage, input) => ({ + sign: () => + transitStage( + + Node Operator ID: {input.nodeOperatorId?.toString()} +
          + Amount:{' '} + + + } + />, + ), + pending: (txHash) => + transitStage( + + Node Operator ID: {input.nodeOperatorId?.toString()} +
          + Amount:{' '} + + + } + />, + ), + success: (_result: undefined, txHash) => + transitStage( + + Node Operator ID: {input.nodeOperatorId?.toString()} +
          + Amount:{' '} + + + } + />, + ), + })); diff --git a/features/delayed-penalty/delayed-penalty-report-form/index.ts b/features/delayed-penalty/delayed-penalty-report-form/index.ts new file mode 100644 index 000000000..192483b60 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-form/index.ts @@ -0,0 +1 @@ +export { DelayedPenaltyReportForm } from './delayed-penalty-report-form'; diff --git a/features/delayed-penalty/delayed-penalty-report-page.tsx b/features/delayed-penalty/delayed-penalty-report-page.tsx new file mode 100644 index 000000000..6e5e9c4b0 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report-page.tsx @@ -0,0 +1,12 @@ +import { FC } from 'react'; + +import { Layout } from 'shared/layout'; +import { DelayedPenaltyPageSwitcher } from 'shared/navigate'; +import { DelayedPenaltyReport } from './delayed-penalty-report'; + +export const DelayedPenaltyReportPage: FC = () => ( + + + + +); diff --git a/features/delayed-penalty/delayed-penalty-report.tsx b/features/delayed-penalty/delayed-penalty-report.tsx new file mode 100644 index 000000000..f980310a1 --- /dev/null +++ b/features/delayed-penalty/delayed-penalty-report.tsx @@ -0,0 +1,15 @@ +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; + +import { DelayedPenaltyReportForm } from './delayed-penalty-report-form'; + +export const DelayedPenaltyReport = () => { + const key = useWeb3Key(); + return ( + <> + + + + + ); +}; diff --git a/features/delayed-penalty/index.ts b/features/delayed-penalty/index.ts new file mode 100644 index 000000000..e1267566f --- /dev/null +++ b/features/delayed-penalty/index.ts @@ -0,0 +1,4 @@ +export * from './delayed-penalty-cancel-page'; +export * from './delayed-penalty-cancel'; +export * from './delayed-penalty-report-page'; +export * from './delayed-penalty-report'; diff --git a/features/stealing/locked-section/index.ts b/features/delayed-penalty/locked-section/index.ts similarity index 100% rename from features/stealing/locked-section/index.ts rename to features/delayed-penalty/locked-section/index.ts diff --git a/features/delayed-penalty/locked-section/locked-section.tsx b/features/delayed-penalty/locked-section/locked-section.tsx new file mode 100644 index 000000000..b4604f1fd --- /dev/null +++ b/features/delayed-penalty/locked-section/locked-section.tsx @@ -0,0 +1,33 @@ +import { useOperatorsWithLockedBond } from 'modules/web3'; +import { TablePagination, TableProvider } from 'providers/table-provider'; +import { FC } from 'react'; +import { Block, Stack, WhenLoaded } from 'shared/components'; +import { LockedTable } from './locked-table'; +import { sortFunctions } from './sort'; + +export const LockedSection: FC = () => { + const { data, isPending: loading } = useOperatorsWithLockedBond(); + + return ( + + + + + + + + + + + ); +}; diff --git a/features/delayed-penalty/locked-section/locked-table.tsx b/features/delayed-penalty/locked-section/locked-table.tsx new file mode 100644 index 000000000..9b9f42174 --- /dev/null +++ b/features/delayed-penalty/locked-section/locked-table.tsx @@ -0,0 +1,51 @@ +import { OperatorWithLockedBond, TOKENS } from '@lidofinance/lido-csm-sdk'; +import { SortButton, useTable } from 'providers/table-provider'; +import { FC } from 'react'; +import { Stack, StatusChip } from 'shared/components'; +import { FormatToken } from 'shared/formatters'; +import { formatDate, isDayInPast } from 'utils'; +import { TableStyle } from './styles'; + +export const LockedTable: FC = () => { + const { data } = useTable(); + + return ( + + + + + Node Operator ID + + + Locked bond amount + + + Expires + + + + + {data.map(({ nodeOperatorId, locked, until }) => ( + + + {nodeOperatorId.toString()} + + + + + + + {formatDate(until, 'dd.MM.yyyy')} + {isDayInPast(until) && ( + + Expired + + )} + + + + ))} + + + ); +}; diff --git a/features/delayed-penalty/locked-section/sort.ts b/features/delayed-penalty/locked-section/sort.ts new file mode 100644 index 000000000..030bc305b --- /dev/null +++ b/features/delayed-penalty/locked-section/sort.ts @@ -0,0 +1,22 @@ +import { OperatorWithLockedBond } from '@lidofinance/lido-csm-sdk'; +import { SortCriteria, SortFunctions } from 'providers/table-provider'; + +const sortByNodeOperatorId: SortCriteria = (item) => [ + item.nodeOperatorId, +]; + +const sortByLocked: SortCriteria = (item) => [ + item.locked, + item.nodeOperatorId, +]; + +const sortByUntil: SortCriteria = (item) => [ + item.until, + item.nodeOperatorId, +]; + +export const sortFunctions: SortFunctions = { + nodeOperatorId: sortByNodeOperatorId, + locked: sortByLocked, + until: sortByUntil, +}; diff --git a/features/delayed-penalty/locked-section/styles.tsx b/features/delayed-penalty/locked-section/styles.tsx new file mode 100644 index 000000000..d2d944531 --- /dev/null +++ b/features/delayed-penalty/locked-section/styles.tsx @@ -0,0 +1,22 @@ +import { Table } from 'shared/components'; +import styled from 'styled-components'; + +export const TableStyle = styled(Table)` + grid-template-columns: auto 1fr 1fr; + + tr { + gap: 12px 32px; + + ${({ theme }) => theme.mediaQueries.md} { + grid-template-columns: 1fr; + + padding: 20px 32px; + } + } + + thead { + ${({ theme }) => theme.mediaQueries.md} { + display: none; + } + } +`; diff --git a/features/dvt/apply-button.tsx b/features/dvt/apply-button.tsx new file mode 100644 index 000000000..f5f0876bd --- /dev/null +++ b/features/dvt/apply-button.tsx @@ -0,0 +1,89 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Button, ButtonProps } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { useNodeOperatorId } from 'modules/web3'; +import { FC } from 'react'; +import { getOperatorTypeQuery } from 'shared/hooks'; +import { LocalLink } from 'shared/navigate'; +import { DvtFormStatus, DvtTypeStatus, useDvtState } from './shared'; + +type ButtonState = { + text: string; + variant: ButtonProps['variant']; + href: PATH; + query?: Record; +}; + +const getButtonState = ( + typeStatus: DvtTypeStatus, + status: DvtFormStatus | undefined, + hasOperator: boolean, +): ButtonState => { + if (typeStatus === 'CLAIMED') { + return { + text: 'View IDVTC status', + variant: 'translucent', + href: PATH.TYPE_DVT_APPLY, + }; + } + if (typeStatus === 'ISSUED') { + // Claiming a type writes onto an existing operator, so without an + // active one the only meaningful action is to create it. + if (!hasOperator) { + return { + text: 'Create IDVTC operator', + variant: undefined, + href: PATH.CREATE, + query: getOperatorTypeQuery(OPERATOR_TYPE.CSM_IDVTC), + }; + } + return { + text: 'Claim IDVTC type', + variant: undefined, + href: PATH.TYPE_DVT_CLAIM, + }; + } + switch (status) { + case 'APPROVED': + case 'REJECTED': + case 'REVIEW': + return { + text: 'View application', + variant: 'translucent', + href: PATH.TYPE_DVT_APPLY, + }; + default: + return { + text: 'Apply for IDVTC', + variant: 'translucent', + href: PATH.TYPE_DVT_APPLY, + }; + } +}; + +type Props = { + size?: ButtonProps['size']; +}; + +export const DvtApplyButton: FC = ({ size }) => { + const { typeStatus, data } = useDvtState(); + const nodeOperatorId = useNodeOperatorId(); + const { text, variant, href, query } = getButtonState( + typeStatus, + data?.status, + nodeOperatorId !== undefined, + ); + + return ( + + + + ); +}; diff --git a/features/dvt/apply-form/apply-form.tsx b/features/dvt/apply-form/apply-form.tsx new file mode 100644 index 000000000..a12ec2051 --- /dev/null +++ b/features/dvt/apply-form/apply-form.tsx @@ -0,0 +1,29 @@ +import { FC, memo } from 'react'; +import { FormBlock } from 'shared/components'; +import { FormLoader, Form } from 'shared/hook-form/form-controller'; +import { ApplyDataProvider, ApplyFormProvider } from './context'; +import { + ClusterMembers, + Confirmations, + MainAddress, + SocialProof, + SubmitButton, +} from './controls'; + +export const ApplyForm: FC = memo(() => ( + + + + +
          + + + + + + +
          +
          +
          +
          +)); diff --git a/features/dvt/apply-form/context/apply-data-provider.tsx b/features/dvt/apply-form/context/apply-data-provider.tsx new file mode 100644 index 000000000..8844f4341 --- /dev/null +++ b/features/dvt/apply-form/context/apply-data-provider.tsx @@ -0,0 +1,40 @@ +import { useQueryClient } from '@tanstack/react-query'; +import { surveysKeys } from 'modules/surveys-sdk'; +import { useDappStatus } from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import type { DvtApplyFormNetworkData } from './types'; + +const useApplyFormNetworkData: NetworkData = () => { + const { address } = useDappStatus(); + + const queryClient = useQueryClient(); + + const revalidate = useCallback(() => { + void queryClient.invalidateQueries({ queryKey: surveysKeys.auth }); + }, [queryClient]); + + return { + data: { + mainAddress: address, + } as DvtApplyFormNetworkData, + isPending: false, + revalidate, + }; +}; + +export const useApplyFormData = useFormData; + +export const ApplyDataProvider: FC = ({ children }) => { + const networkData = useApplyFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/dvt/apply-form/context/apply-form-provider.tsx b/features/dvt/apply-form/context/apply-form-provider.tsx new file mode 100644 index 000000000..69a037d32 --- /dev/null +++ b/features/dvt/apply-form/context/apply-form-provider.tsx @@ -0,0 +1,87 @@ +import { FC, PropsWithChildren, useEffect, useRef } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, + useFormDefaultValues, +} from 'shared/hook-form/form-controller'; +import { useDvtState } from 'features/dvt/shared'; +import { CLUSTER_SIZE } from './consts'; +import type { ClusterMember, DvtApplyFormInputType } from './types'; +import { useApplyFormData } from './apply-data-provider'; +import { useApplyFlowResolver } from './use-apply-flow'; +import { useApplyFormValidation } from './use-apply-form-validation'; +import { useFormPersist } from './use-form-persist'; + +const emptyMember: ClusterMember = { + address: '', + signature: '', +}; + +const createEmptyMembers = (): ClusterMember[] => + Array.from({ length: CLUSTER_SIZE }, () => ({ ...emptyMember })); + +export const ApplyFormProvider: FC = ({ children }) => { + const { mainAddress } = useApplyFormData(true); + const { data } = useDvtState(); + const submittedAt = data + ? new Date(data.updatedAt ?? data.createdAt).getTime() + : undefined; + const { draft, save, clear } = useFormPersist(mainAddress, submittedAt); + const resolver = useApplyFormValidation(); + const timeoutRef = useRef>(); + + const defaultValues = useFormDefaultValues(() => { + const emptyDefaults: DvtApplyFormInputType = { + clusterMembers: createEmptyMembers(), + discordLink: '', + telegramUsername: '', + confirmed: false, + }; + + if (!draft) return emptyDefaults; + + const { savedAt: _savedAt, ...stored } = draft; + + return { + ...emptyDefaults, + ...stored, + clusterMembers: stored.clusterMembers?.length + ? stored.clusterMembers.map((m) => ({ ...emptyMember, ...m })) + : emptyDefaults.clusterMembers, + confirmed: false, + }; + }); + + const formObject = useForm({ + defaultValues, + resolver, + mode: 'onChange', + }); + + const { watch } = formObject; + + useEffect(() => { + const subscription = watch((values) => { + if (timeoutRef.current) clearTimeout(timeoutRef.current); + timeoutRef.current = setTimeout(() => { + const { confirmed: _, ...toPersist } = values; + save(toPersist as Partial); + }, 1000); + }); + return () => { + subscription.unsubscribe(); + if (timeoutRef.current) clearTimeout(timeoutRef.current); + }; + }, [watch, save]); + + const submitter = useFlowSubmit(useApplyFlowResolver(clear)); + + return ( + + + {children} + + + ); +}; diff --git a/features/dvt/apply-form/context/consts.ts b/features/dvt/apply-form/context/consts.ts new file mode 100644 index 000000000..adc67c230 --- /dev/null +++ b/features/dvt/apply-form/context/consts.ts @@ -0,0 +1 @@ +export const CLUSTER_SIZE = 4; diff --git a/features/dvt/apply-form/context/index.ts b/features/dvt/apply-form/context/index.ts new file mode 100644 index 000000000..89ebd98ea --- /dev/null +++ b/features/dvt/apply-form/context/index.ts @@ -0,0 +1,5 @@ +export * from './apply-data-provider'; +export * from './apply-form-provider'; +export * from './consts'; +export * from './types'; +export * from './use-verify-message'; diff --git a/features/dvt/apply-form/context/types.ts b/features/dvt/apply-form/context/types.ts new file mode 100644 index 000000000..319eb48e8 --- /dev/null +++ b/features/dvt/apply-form/context/types.ts @@ -0,0 +1,20 @@ +import { Address } from 'viem'; + +export type ClusterMember = { + address: string; + signature: string; + verified?: boolean; + discordHandle?: string; + telegramUsername?: string; +}; + +export type DvtApplyFormInputType = { + clusterMembers: ClusterMember[]; + discordLink: string; + telegramUsername: string; + confirmed: boolean; +}; + +export type DvtApplyFormNetworkData = { + mainAddress: Address; +}; diff --git a/features/dvt/apply-form/context/use-apply-flow.ts b/features/dvt/apply-form/context/use-apply-flow.ts new file mode 100644 index 000000000..21f6956d4 --- /dev/null +++ b/features/dvt/apply-form/context/use-apply-flow.ts @@ -0,0 +1,77 @@ +import { DvtApplyDto, DvtResponseDto, useDvtState } from 'features/dvt/shared'; +import { endpoints, useSurveysMutation } from 'modules/surveys-sdk'; +import { useCallback } from 'react'; +import type { + Executable, + FlowResolver, +} from 'shared/hook-form/form-controller'; +import type { DvtApplyFormInputType, DvtApplyFormNetworkData } from './types'; +import { useModalStages } from './use-modal-stages'; + +export type ApplyFlow = { action: 'submit' } & Executable; + +const transformFormDataToApiPayload = ( + form: DvtApplyFormInputType, + data: DvtApplyFormNetworkData, +): DvtApplyDto => ({ + mainAddress: data.mainAddress, + discordLink: form.discordLink, + telegramUsername: form.telegramUsername || undefined, + clusterMembers: form.clusterMembers.map( + ({ address, signature, discordHandle, telegramUsername }) => ({ + address, + signature, + discordHandle: discordHandle || undefined, + telegramUsername: telegramUsername || undefined, + }), + ), +}); + +export const useApplyFlowResolver = ( + clearPersistedForm?: () => void, +): FlowResolver => { + const { txModalStages: stages } = useModalStages(); + const { reset } = useDvtState(); + const mutation = useSurveysMutation( + endpoints.dvtApply, + { mutationKey: ['dvt-apply'] }, + ); + + return useCallback( + (input, data) => ({ + action: 'submit' as const, + submit: async () => { + const apiPayload = transformFormDataToApiPayload(input, data); + + try { + stages.pending(); + await mutation.mutateAsync(apiPayload); + window.scrollTo({ top: 0 }); + reset(false); + clearPersistedForm?.(); + stages.success(); + } catch (error: any) { + let errorMessage = 'Something went wrong'; + let errorDetails: string[] = []; + + if (error?.response?.data?.message) { + const messages = error.response.data.message; + if (Array.isArray(messages)) { + errorDetails = messages; + errorMessage = `Validation failed: ${messages.length} error${messages.length > 1 ? 's' : ''}`; + } else if (typeof messages === 'string') { + errorMessage = messages; + } + } else if (error?.message) { + errorMessage = error.message; + } + + window.scrollTo({ top: 0 }); + stages.failed({ message: errorMessage, details: errorDetails }); + throw error; + } + }, + }), + [clearPersistedForm, mutation, reset, stages], + ); +}; diff --git a/features/dvt/apply-form/context/use-apply-form-validation.ts b/features/dvt/apply-form/context/use-apply-form-validation.ts new file mode 100644 index 000000000..431fd2db6 --- /dev/null +++ b/features/dvt/apply-form/context/use-apply-form-validation.ts @@ -0,0 +1,112 @@ +import { + useFormValidation, + ValidationError, +} from 'shared/hook-form/validation'; +import { isAddress, isAddressEqual, isHex } from 'viem'; +import { useApplyFormData } from './apply-data-provider'; +import { CLUSTER_SIZE } from './consts'; +import type { DvtApplyFormInputType, DvtApplyFormNetworkData } from './types'; +import { useRawVerifyMessage } from './use-verify-message'; +import { useValidateIcsProof } from './use-validate-ics-proof'; + +const discordMessageRegex = /^https:\/\/discord\.com\/channels\/\d+\/\d+\/\d+$/; + +export const useApplyFormValidation = () => { + const { mainAddress } = useApplyFormData(true); + const verifyMessage = useRawVerifyMessage(mainAddress); + const validateIcsProof = useValidateIcsProof(); + + return useFormValidation( + 'clusterMembers', + async ( + { clusterMembers, discordLink, confirmed }, + { mainAddress: _mainAddress }, + validate, + ) => { + await Promise.all( + clusterMembers + .slice(0, CLUSTER_SIZE) + .map(async ({ address, signature, verified }, index) => { + const addressPath = `clusterMembers.${index}.address` as any; + const signaturePath = `clusterMembers.${index}.signature` as any; + + await validate(addressPath, async () => { + if (!address || !isAddress(address)) { + throw new ValidationError(addressPath, ''); + } + + const hasDuplicateAddresses = clusterMembers.some( + (a, i) => + i !== index && + isAddress(a.address) && + isAddressEqual(address, a.address), + ); + + if (hasDuplicateAddresses) { + throw new ValidationError( + addressPath, + 'Duplicate addresses are not allowed', + ); + } + + await validateIcsProof(address, addressPath); + }); + + await validate(signaturePath, async () => { + if (!signature || !isHex(signature)) { + throw new ValidationError(signaturePath, ''); + } + + if (verified) return; + + try { + if (!isAddress(address)) { + throw new ValidationError(addressPath, ''); + } + + const isValid = await verifyMessage({ address, signature }); + + if (!isValid) { + throw new ValidationError( + signaturePath, + 'Invalid signature for this address and message', + ); + } + } catch { + throw new ValidationError( + signaturePath, + 'Invalid signature for this address and message', + ); + } + }); + }), + ); + + await validate('discordLink', () => { + if (!discordLink) { + throw new ValidationError( + 'discordLink', + 'Discord message link is required', + ); + } + + if (!discordMessageRegex.test(discordLink)) { + throw new ValidationError( + 'discordLink', + 'Must be a valid Discord message URL', + ); + } + }); + + await validate('confirmed', () => { + if (!confirmed) { + throw new ValidationError( + 'confirmed', + 'You must confirm the application', + ); + } + }); + }, + [verifyMessage, validateIcsProof], + ); +}; diff --git a/features/dvt/apply-form/context/use-form-persist.ts b/features/dvt/apply-form/context/use-form-persist.ts new file mode 100644 index 000000000..594a09796 --- /dev/null +++ b/features/dvt/apply-form/context/use-form-persist.ts @@ -0,0 +1,37 @@ +import { useCallback, useRef } from 'react'; +import { Address } from 'viem'; +import { useLocalStorage } from 'shared/hooks/use-local-storage'; +import { DvtApplyFormInputType } from './types'; + +type PersistedDraft = Partial & { savedAt: number }; + +export const useFormPersist = ( + address: Address | undefined, + // last time the server-side application changed (createdAt/updatedAt) + submittedAt?: number, +) => { + const key = address ? `dvt-apply-${address.toLowerCase()}` : undefined; + const [stored, setStored] = useLocalStorage(key, null); + const stoppedRef = useRef(false); + + const clear = useCallback(() => { + // block any pending debounced write so the cleared state sticks + stoppedRef.current = true; + setStored(null); + }, [setStored]); + + const save = useCallback( + (values: Partial) => { + if (stoppedRef.current) return; + setStored({ ...values, savedAt: Date.now() }); + }, + [setStored], + ); + + // a draft is valid only if it was edited after the latest submission, + // so leftovers from a rejected attempt never resurface + const draft = + stored && (!submittedAt || stored.savedAt > submittedAt) ? stored : null; + + return { draft, save, clear } as const; +}; diff --git a/features/dvt/apply-form/context/use-modal-stages.tsx b/features/dvt/apply-form/context/use-modal-stages.tsx new file mode 100644 index 000000000..436089348 --- /dev/null +++ b/features/dvt/apply-form/context/use-modal-stages.tsx @@ -0,0 +1,59 @@ +import { + TransactionModalTransitStage, + TxStageFail, + TxStagePending, + TxStageSuccess, + useTransactionModalStage, +} from 'shared/transaction-modal'; +import { extractErrorMessage, getErrorCode } from 'utils'; + +const getModalStages = (transitStage: TransactionModalTransitStage) => ({ + pending: () => + transitStage( + , + ), + + success: () => + transitStage( + , + ), + + failed: (error: unknown) => { + let errorContent; + + if (typeof error === 'object' && error !== null && 'details' in error) { + const errorObj = error as { message: string; details: string[] }; + errorContent = ( + <> + {errorObj.message} +
          + {errorObj.details.length > 0 && ( +
            + {errorObj.details.map((detail, index) => ( +
          • {detail}
          • + ))} +
          + )} + + ); + } else { + errorContent = extractErrorMessage(error); + } + + return transitStage( + , + ); + }, +}); + +export const useModalStages = () => useTransactionModalStage(getModalStages); diff --git a/features/dvt/apply-form/context/use-validate-ics-proof.ts b/features/dvt/apply-form/context/use-validate-ics-proof.ts new file mode 100644 index 000000000..cbc1e324d --- /dev/null +++ b/features/dvt/apply-form/context/use-validate-ics-proof.ts @@ -0,0 +1,22 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { ValidationError } from 'shared/hook-form/validation'; +import invariant from 'tiny-invariant'; +import { Address } from 'viem'; + +export const useValidateIcsProof = () => { + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useCallback( + async (address: Address, fieldPath: string) => { + invariant(sdk, 'CSM SDK is required for ICS proof validation'); + const proof = await sdk.icsGate.getProof(address); + + if (!proof) { + throw new ValidationError(fieldPath, 'Address is not ICS-approved'); + } + }, + [sdk], + ); +}; diff --git a/features/dvt/apply-form/context/use-verify-message.ts b/features/dvt/apply-form/context/use-verify-message.ts new file mode 100644 index 000000000..3a98098c9 --- /dev/null +++ b/features/dvt/apply-form/context/use-verify-message.ts @@ -0,0 +1,55 @@ +import { useMainnetOnlyWagmi } from 'modules/web3/web3-provider/web3-provider'; +import { useCallback } from 'react'; +import { Address, Hex, isAddress, PublicClient } from 'viem'; +import { usePublicClient } from 'wagmi'; +import { generateClusterMemberMessage, generateDiscordMessage } from './utils'; +import { useApplyFormData } from './apply-data-provider'; + +type VerifyMessageProps = { + address: Address; + signature: Hex; +}; + +export const useClusterMemberMessage = (address?: string) => { + const { mainAddress } = useApplyFormData(true); + + return address && isAddress(address) + ? generateClusterMemberMessage(address, mainAddress) + : ''; +}; + +export const useDiscordMessage = () => { + const { mainAddress } = useApplyFormData(true); + return generateDiscordMessage(mainAddress); +}; + +export const useRawVerifyMessage = (mainAddress: Address) => { + const { publicClientMainnet } = useMainnetOnlyWagmi(); + const publicClient = usePublicClient(); + + return useCallback( + async ({ address, signature }: VerifyMessageProps) => { + const message = generateClusterMemberMessage(address, mainAddress); + const clients = [publicClient] as PublicClient[]; + if (publicClientMainnet.chain?.id !== publicClient?.chain.id) { + clients.push(publicClientMainnet); + } + + const isValid = ( + await Promise.all( + clients.map((client) => + client?.verifyMessage({ address, message, signature }), + ), + ) + ).some(Boolean); + + return isValid; + }, + [mainAddress, publicClient, publicClientMainnet], + ); +}; + +export const useVerifyMessage = () => { + const { mainAddress } = useApplyFormData(true); + return useRawVerifyMessage(mainAddress); +}; diff --git a/features/dvt/apply-form/context/utils.ts b/features/dvt/apply-form/context/utils.ts new file mode 100644 index 000000000..e0611d164 --- /dev/null +++ b/features/dvt/apply-form/context/utils.ts @@ -0,0 +1,10 @@ +import { Address } from 'viem'; + +export const generateDiscordMessage = (address: Address) => + `This post is proof that I am the owner of this Discord account. My address to get verified for IDVTC: ${address.toLowerCase()}`; + +export const generateClusterMemberMessage = ( + memberAddress: Address, + mainAddress: Address, +) => + `Verify ownership of address ${memberAddress.toLowerCase()} for DVT cluster with main address ${mainAddress.toLowerCase()}`; diff --git a/features/dvt/apply-form/controls/cluster-member-item.tsx b/features/dvt/apply-form/controls/cluster-member-item.tsx new file mode 100644 index 000000000..45485fd67 --- /dev/null +++ b/features/dvt/apply-form/controls/cluster-member-item.tsx @@ -0,0 +1,264 @@ +import { + Button, + ButtonIcon, + External, + Input, + Text, +} from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { FC, useCallback, useState } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { + Chip, + CopyButton, + FormTitle, + MatomoLink, + Stack, +} from 'shared/components'; +import { VerifiedIcon } from 'shared/components/input-address/styles'; +import { SquaredChip } from 'shared/components/status-chip/status-chip'; +import { + AddressInputHookForm, + TextInputHookForm, +} from 'shared/hook-form/controls'; +import { isAddress, isHex } from 'viem'; +import { + useClusterMemberMessage, + useVerifyMessage, + type DvtApplyFormInputType, +} from '../context'; +import { ClusterMemberCard } from '../styles'; + +type ClusterMemberItemProps = { + index: number; +}; + +export const ClusterMemberItem: FC = ({ index }) => { + const watchedAddress = useWatch({ + name: `clusterMembers.${index}.address` as const, + }) as string; + + const verified = useWatch({ + name: `clusterMembers.${index}.verified` as const, + }); + + const { getValues, setError, clearErrors, setValue, trigger } = + useFormContext(); + + const message = useClusterMemberMessage(watchedAddress); + + const [isVerifying, setIsVerifying] = useState(false); + + const verifyMessage = useVerifyMessage(); + + const onVerify = useCallback(async () => { + if (isVerifying || verified) return; + + const currentMembers = getValues('clusterMembers'); + const { address, signature } = currentMembers[index]; + + if (!isAddress(address)) { + setError(`clusterMembers.${index}.address`, { + type: 'manual', + message: 'Invalid Ethereum address', + }); + return; + } + + if (!isHex(signature)) { + setError(`clusterMembers.${index}.signature`, { + type: 'manual', + message: 'Invalid signature format', + }); + return; + } + + setIsVerifying(true); + + try { + const isAddressValid = await trigger(`clusterMembers.${index}.address`); + if (!isAddressValid) return; + + const isValid = await verifyMessage({ address, signature }); + + if (isValid) { + clearErrors(`clusterMembers.${index}.signature`); + setValue(`clusterMembers.${index}.verified`, true); + } else { + setError(`clusterMembers.${index}.signature`, { + type: 'manual', + message: 'Invalid signature for this address and message', + }); + } + } catch (_error) { + setError(`clusterMembers.${index}.signature`, { + type: 'manual', + message: 'Invalid signature format or verification failed', + }); + } finally { + setIsVerifying(false); + } + }, [ + clearErrors, + getValues, + index, + setError, + trigger, + verifyMessage, + isVerifying, + verified, + setValue, + ]); + + const onClear = useCallback(() => { + setValue(`clusterMembers.${index}.address`, ''); + setValue(`clusterMembers.${index}.signature`, ''); + setValue(`clusterMembers.${index}.verified`, false); + }, [index, setValue]); + + return ( + + + + + Cluster member #{index + 1} + + {verified ? ( + + Verified + + + ) : ( + + Unverified + + )} + + + {verified ? ( + + + Clear + + } + /> + + + Optional}>Add contacts + + + + + + + ) : ( + + + + Step 1. Insert cluster member #{index + 1} Ethereum address and + send the link to this member to sign the transaction on + Etherscan. + + + + + + } + size="xs" + variant="translucent" + > + Sign + + + + } + /> + + + + + Step 2. Copy the signature and past in the field below + + void onVerify()} + disabled={isVerifying} + data-testid="verifySignatureBtn" + > + {isVerifying ? 'Verifying...' : 'Verify'} + + } + /> + + + + + Add contacts + Optional + + + + + + + + )} + + + ); +}; diff --git a/features/dvt/apply-form/controls/cluster-members.tsx b/features/dvt/apply-form/controls/cluster-members.tsx new file mode 100644 index 000000000..efdd433ae --- /dev/null +++ b/features/dvt/apply-form/controls/cluster-members.tsx @@ -0,0 +1,40 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { useWatch } from 'react-hook-form'; +import { FormTitle, Stack } from 'shared/components'; +import { CLUSTER_SIZE, type DvtApplyFormInputType } from '../context'; +import { ProgressBar, ProgressBarFill, ProgressBarTrack } from '../styles'; +import { ClusterMemberItem } from './cluster-member-item'; + +export const ClusterMembers: FC = () => { + const clusterMembers = useWatch({ + name: 'clusterMembers', + }) as DvtApplyFormInputType['clusterMembers']; + + const verifiedCount = clusterMembers?.filter((m) => m.verified).length ?? 0; + + return ( + + + Cluster member addresses + + Verify ownership of {CLUSTER_SIZE} additional Ethereum addresses in + your validator cluster. + + + + + + + + + {verifiedCount} / {CLUSTER_SIZE} verified + + + + {Array.from({ length: CLUSTER_SIZE }, (_, index) => ( + + ))} + + ); +}; diff --git a/features/dvt/apply-form/controls/confirmations.tsx b/features/dvt/apply-form/controls/confirmations.tsx new file mode 100644 index 000000000..b9e9c46e1 --- /dev/null +++ b/features/dvt/apply-form/controls/confirmations.tsx @@ -0,0 +1,27 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { CheckboxHookForm } from 'shared/hook-form/controls'; +import { ConfirmationList } from '../styles'; + +export const Confirmations: FC = () => { + return ( + + + + I confirm that: + +
        • + Cluster participants understand the requirements and eligibility + criteria +
        • +
        • + Cluster participants agree to enroll in monitoring via DVT provider + specific tooling (e.g. Obol Grafana metrics or automatic SSV Network + metrics) +
        • +
          +
          +
          + ); +}; diff --git a/features/dvt/apply-form/controls/index.ts b/features/dvt/apply-form/controls/index.ts new file mode 100644 index 000000000..59bcffd9b --- /dev/null +++ b/features/dvt/apply-form/controls/index.ts @@ -0,0 +1,5 @@ +export * from './main-address'; +export * from './social-proof'; +export * from './cluster-members'; +export * from './confirmations'; +export * from './submit-button'; diff --git a/features/dvt/apply-form/controls/main-address-tooltip-content.tsx b/features/dvt/apply-form/controls/main-address-tooltip-content.tsx new file mode 100644 index 000000000..29dcd6e90 --- /dev/null +++ b/features/dvt/apply-form/controls/main-address-tooltip-content.tsx @@ -0,0 +1,30 @@ +import { FC } from 'react'; +import styled from 'styled-components'; + +const TooltipText = styled.div` + p + *, + li + * { + margin-top: ${({ theme }) => theme.spaceMap.xs}px; + } +`; + +export const MainAddressTooltipContent: FC = () => ( + +

          + If your application is approved, this Main address will be able to claim + the IDVTC operator type. +

          +

          Choose the Main address based on your setup:

          +
            +
          • + If you are upgrading an existing Node Operator to IDVTC, use the owner + address of that Node Operator. +
          • +
          • + If you are creating a new Node Operator, use the address that should + claim the IDVTC type. This is usually a multisig controlled by your + cluster. +
          • +
          +
          +); diff --git a/features/dvt/apply-form/controls/main-address.tsx b/features/dvt/apply-form/controls/main-address.tsx new file mode 100644 index 000000000..1db923ba2 --- /dev/null +++ b/features/dvt/apply-form/controls/main-address.tsx @@ -0,0 +1,33 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { FormTitle, IconTooltip, InputAddress, Stack } from 'shared/components'; +import { VerifiedChip } from 'shared/components/input-address/verified-chip'; +import { useApplyFormData } from '../context'; +import { MainAddressTooltipContent } from './main-address-tooltip-content'; + +export const MainAddress: FC = () => { + const { mainAddress } = useApplyFormData(true); + + return ( + + + Main address + + You are requesting IDVTC operator type for the following address: + } /> + + + + Main address Verified + + } + value={mainAddress} + /> + + ); +}; diff --git a/features/dvt/apply-form/controls/social-proof.tsx b/features/dvt/apply-form/controls/social-proof.tsx new file mode 100644 index 000000000..21c307d51 --- /dev/null +++ b/features/dvt/apply-form/controls/social-proof.tsx @@ -0,0 +1,98 @@ +import { Input, Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { CategoryItemsWrapper } from '../styles'; +import { FC } from 'react'; +import { + Chip, + CopyButton, + FormTitle, + IconTooltip, + MatomoLink, + Stack, +} from 'shared/components'; +import { TextInputHookForm } from 'shared/hook-form/controls'; +import { useDiscordMessage } from '../context'; + +export const SocialProof: FC = () => { + const discordMessage = useDiscordMessage(); + + return ( + + + Socials + + You must add your social accounts. To prove you own an account, post a + message. For more info see{' '} + + the guide + + + + + {/* Discord Section */} + + + Discord + + + + + + Step 1. Prove the ownership of the Discord account by posting the + following message to{' '} + + the CSM channel + {' '} + + + + e.target.select()} + onClick={(e) => (e.target as HTMLInputElement).select()} + value={discordMessage} + fullwidth + rightDecorator={} + /> + + + + Step 2. Paste the link to this message + + + + + + + {/* Telegram Section */} + + + + Telegram + + Optional + + + + + + ); +}; diff --git a/features/dvt/apply-form/controls/submit-button.tsx b/features/dvt/apply-form/controls/submit-button.tsx new file mode 100644 index 000000000..8c3e5e235 --- /dev/null +++ b/features/dvt/apply-form/controls/submit-button.tsx @@ -0,0 +1,30 @@ +import { FC } from 'react'; +import { useWatch } from 'react-hook-form'; +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; +import { CLUSTER_SIZE, type DvtApplyFormInputType } from '../context'; + +export const SubmitButton: FC = () => { + const confirmed = useWatch({ + name: 'confirmed', + }); + const discordLink = useWatch({ + name: 'discordLink', + }); + const clusterMembers = useWatch({ + name: 'clusterMembers', + }); + + const isComplete = + !!confirmed && + !!discordLink && + (clusterMembers?.length ?? 0) >= CLUSTER_SIZE && + clusterMembers + .slice(0, CLUSTER_SIZE) + .every((m) => !!m?.address && !!m?.signature); + + return ( + + Submit application + + ); +}; diff --git a/features/dvt/apply-form/index.ts b/features/dvt/apply-form/index.ts new file mode 100644 index 000000000..29b4f29c8 --- /dev/null +++ b/features/dvt/apply-form/index.ts @@ -0,0 +1 @@ +export * from './apply-form'; diff --git a/features/dvt/apply-form/styles.ts b/features/dvt/apply-form/styles.ts new file mode 100644 index 000000000..5690f6558 --- /dev/null +++ b/features/dvt/apply-form/styles.ts @@ -0,0 +1,62 @@ +import { Theme } from '@lidofinance/lido-ui'; +import { StackStyle } from 'shared/components'; +import styled from 'styled-components'; + +export const ClusterMemberCard = styled.div` + border: 1px solid var(--lido-color-border); + border-radius: 10px; + padding: 20px; + background: linear-gradient( + 180deg, + var(--lido-color-accentControlBg) 0%, + var(--lido-color-accentControlBg) 100%, + #fff + ); +`; + +export const ProgressBar = styled.div` + display: flex; + align-items: center; + gap: ${({ theme }) => theme.spaceMap.sm}px; + border-radius: ${({ theme }) => theme.borderRadiusesMap.lg}px; +`; + +export const ProgressBarTrack = styled.div` + height: 4px; + flex: 1; + border-radius: 2px; + background: var(--lido-color-border); + overflow: hidden; +`; + +export const ProgressBarFill = styled.div<{ $progress: number }>` + height: 100%; + width: ${({ $progress }) => Math.min(Math.max($progress, 0), 1) * 100}%; + border-radius: 2px; + background: var(--lido-color-primary); + transition: width 0.2s ease; +`; + +export const ConfirmationList = styled.ul` + margin: 4px 0 0; + padding-left: 20px; +`; + +// TODO: check similar component in feature/ics +export const CategoryItemsWrapper = styled(StackStyle).attrs({ + $direction: 'column', +})<{ $offset?: keyof Theme['spaceMap'] }>` + position: relative; + padding-left: ${({ theme, $offset = 'xl' }) => theme.spaceMap[$offset]}px; + + &:before { + content: ''; + display: block; + position: absolute; + width: 2px; + height: 100%; + left: 0px; + background: var(--lido-color-border); + border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px; + } +`; diff --git a/features/dvt/description/application-flow.tsx b/features/dvt/description/application-flow.tsx new file mode 100644 index 000000000..73d7478a6 --- /dev/null +++ b/features/dvt/description/application-flow.tsx @@ -0,0 +1,51 @@ +import { Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts'; +import { FC, PropsWithChildren } from 'react'; +import { Stack } from 'shared/components'; +import { LocalLink } from 'shared/navigate'; +import { Number, StepContent, StepWrapper } from './styles'; + +const Step: FC> = ({ + number, + title, + children, +}) => { + return ( + + {number} + +

          {title}

          +

          {children}

          +
          +
          + ); +}; + +export const ApplicationFlow: FC = () => { + return ( + + + Application Flow + + + People interested in being included in the Identified DVT Cluster list + must submit an application on the " + Application form + " sub-tab + + + After submission, the application undergoes semi-automated checks to + validate the provided information + + + If approved, the CSM Committee will initiate an Easy Track motion to + assign the operator type to the applicant's address + + + Once the operator type is issued, it can be claimed via the CSM UI (for + existing operators), or it will be assigned automatically upon operator + creation (for new operators) + + + ); +}; diff --git a/features/dvt/description/criteria-data.tsx b/features/dvt/description/criteria-data.tsx new file mode 100644 index 000000000..dc6e5c4cf --- /dev/null +++ b/features/dvt/description/criteria-data.tsx @@ -0,0 +1,116 @@ +import { ReactNode } from 'react'; + +export type CriterionItem = { + id: string; + title: string; + content: ReactNode; +}; + +export const CRITERIA: CriterionItem[] = [ + { + id: 'cluster-composition', + title: 'Cluster composition and proof of independence', + content: ( +
            +
          • One CSM operator can be a participant in only one IDVTC.
          • +
          • A DVT cluster must consist of 4 independent participants.
          • +
          • + Each participant must have an approved ICS application (or must be an + ICS operator). +
          • +
          • + Keys must be generated via DKG with artifacts including: +
              +
            • cluster-lock.json file for Obol clusters.
            • +
            • proofs.json file for SSV clusters.
            • +
            +
          • +
          • + The cluster formation requires signatures from each member, linking + their ICS identity to the cluster. +
          • +
          • + The cluster must provide a contact information Lido contributors can + use in case of issues with the DKG verification. +
          • +
          • + Operators must agree to enrol in monitoring via DVT provider specific + tooling (e.g. Obol Grafana metrics, automatic SSV Network metrics). +
          • +
          + ), + }, + { + id: 'obligation-to-run-dvt', + title: 'Obligation to run DVT', + content: ( +
            +
          • IDVTC operators must run validators using Obol or SSV.
          • +
          • + IDVTC operators must generate the keys via DKG ceremony and provide + proof of the output. +
          • +
          • + Switching DVT providers is allowed as long as it remains within the + approved set and is reported/observable (will require exit-enter + procedure). +
          • +
          + ), + }, + { + id: 'downgrade-policy', + title: 'Downgrade policy', + content: ( + <> +

          + If an IDVTC is detected and reported by the CSM committee as not using + DVT (or otherwise failing type requirements): +

          +
            +
          • The operator's type is downgraded.
          • +
          • + The operator fee and bond requirements are changed accordingly to a + default CSM type, which will likely cause ejection of some of the + keys due to them becoming unbonded. CSM Committee can also consider + downgrading participants' ICS type in case such violation is + committed. +
          • +
          + + ), + }, + { + id: 'replacing-cluster-member', + title: 'Replacing a cluster member', + content: ( + <> +

          + Identified DVTCs may replace participants over time (e.g. if someone + stops operating), while keeping the cluster within the IDVTC operator + type requirements. +

          +

          If a participant is replaced:

          +
            +
          • The new participant must be another ICS-approved participant.
          • +
          • + No participant may be a member of more than one IDVTC at the same + time. +
          • +
          • The cluster must submit a new 4-signature cluster statement.
          • +
          • Monitoring must remain in place for all nodes.
          • +
          + + ), + }, + { + id: 'ics-idvtc-compatibility', + title: 'ICS <> IDVTC compatibility', + content: ( +

          + One CSM operator can have only one Node Operator of the ICS type, as + well as be a participant in only one IDVTC. +

          + ), + }, +]; diff --git a/features/dvt/description/index.ts b/features/dvt/description/index.ts new file mode 100644 index 000000000..5a3533bca --- /dev/null +++ b/features/dvt/description/index.ts @@ -0,0 +1,3 @@ +export * from './application-flow'; +export * from './introduction'; +export * from './requirements-criteria'; diff --git a/features/dvt/description/introduction.tsx b/features/dvt/description/introduction.tsx new file mode 100644 index 000000000..c76ee3cb0 --- /dev/null +++ b/features/dvt/description/introduction.tsx @@ -0,0 +1,21 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; + +export const Introduction: FC = () => { + return ( + + + Introduction + + + Identified DVT Clusters (IDVTC) is designed for DVT Clusters and creates + a more capital-efficient path for independent stakers who are willing to + identify themselves and operate validators collaboratively via DVT. This + approach combines the trust properties of ICS with the operational + resilience of DVT, aligning incentives for small independent operators + who share validator rewards within a cluster. + + + ); +}; diff --git a/features/dvt/description/requirements-criteria.tsx b/features/dvt/description/requirements-criteria.tsx new file mode 100644 index 000000000..0419273a3 --- /dev/null +++ b/features/dvt/description/requirements-criteria.tsx @@ -0,0 +1,32 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { CRITERIA } from './criteria-data'; +import { CriteriaAccordionStyle, CriteriaContent } from './styles'; + +export const RequirementsCriteria: FC = () => { + return ( + + + Requirements and Criteria + + + To be included in the list, applicants must meet all the criteria and be + approved by the CSM Committee. + + {CRITERIA.map((criterion) => ( + + {criterion.title} + + } + > + {criterion.content} + + ))} + + ); +}; diff --git a/features/dvt/description/styles.ts b/features/dvt/description/styles.ts new file mode 100644 index 000000000..c44fabfd4 --- /dev/null +++ b/features/dvt/description/styles.ts @@ -0,0 +1,112 @@ +import { Block } from '@lidofinance/lido-ui'; +import { AccordionNavigatable } from 'shared/components/accordion-navigatable'; +import styled from 'styled-components'; + +export const BlockStyle = styled(Block)` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spaceMap.xxl}px; +`; + +export const Number = styled.div` + display: flex; + flex-direction: row; + flex-wrap: wrap; + width: 32px; + height: 32px; + justify-content: center; + align-items: center; + + border-radius: 100%; + border: 1px solid var(--lido-color-border); + + color: var(--lido-color-text); + font-size: 14px; + font-weight: 700; + line-height: 24px; + + margin-top: -4px; +`; + +export const StepWrapper = styled.div` + display: flex; + flex-direction: row; + gap: ${({ theme }) => theme.spaceMap.md}px; + align-items: start; + position: relative; + + &:not(:last-child) ${Number}:after { + content: ''; + position: absolute; + top: 28px; + bottom: -12px; + width: 1px; + background: var(--lido-color-border); + } +`; + +export const StepContent = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; + flex: 1 0 40%; + text-align: left; + + h3 { + color: var(--lido-color-text); + font-size: 14px; + font-weight: 700; + line-height: 24px; + } + + p { + color: var(--lido-color-textSecondary); + font-size: 12px; + font-weight: 400; + line-height: 20px; + } +`; + +export const CriteriaAccordionStyle = styled(AccordionNavigatable)` + margin: 0; + & > [role='button'] { + padding: 0; + min-height: 24px; + } + & > [role='region'] > div { + padding: 4px 0 0; + } + + p, + ul, + ol { + margin: 0; + } +`; + +export const CriteriaContent = styled.div` + color: var(--lido-color-textSecondary); + font-size: 12px; + font-weight: 400; + line-height: 20px; + + ul { + list-style-type: disc; + padding-left: 18px; + margin: 0; + + ul { + list-style-type: disc; + padding-left: 18px; + } + } + + li { + margin-bottom: 0; + } + + p { + margin: 0; + } +`; diff --git a/features/dvt/dvt-apply-page.tsx b/features/dvt/dvt-apply-page.tsx new file mode 100644 index 000000000..d8f158f0f --- /dev/null +++ b/features/dvt/dvt-apply-page.tsx @@ -0,0 +1,20 @@ +import { FC } from 'react'; + +import { FAQ_OPERATOR_TYPE } from 'faq'; +import { Faq, TypeBackButton } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { DvtPageSwitcher } from 'shared/navigate'; +import { DvtApply } from './dvt-apply'; + +export const DvtApplyPage: FC = () => ( + } + > + + + + +); diff --git a/features/dvt/dvt-apply.tsx b/features/dvt/dvt-apply.tsx new file mode 100644 index 000000000..b5c79a676 --- /dev/null +++ b/features/dvt/dvt-apply.tsx @@ -0,0 +1,78 @@ +import { Block, Text } from '@lidofinance/lido-ui'; +import { useSiweAuth } from 'modules/siwe'; +import { useDappStatus } from 'modules/web3'; +import { FC } from 'react'; +import { NoSSRWrapper, Stack, WhenLoaded } from 'shared/components'; +import { Connect } from 'shared/wallet'; +import { ApplyForm } from './apply-form'; +import { FormStatus } from './form-status/form-status'; +import { ProofStatus } from './form-status/proof-status'; +import { DvtProviders, useDvtState } from './shared'; +import { SiweSignIn } from './siwe-sign-in/siwe-sign-in'; + +const DvtApplyContent: FC = () => { + const { isAccountActive } = useDappStatus(); + const { token } = useSiweAuth(); + const { typeStatus, data, isPending, isTypePending, applyMode, reset } = + useDvtState(); + + if (!isAccountActive) { + return ( + + + + + Connect your wallet + + + Connect your wallet and sign a verification message to continue. + + + + + + ); + } + + if (isTypePending) { + return ( + + + + ); + } + + if (typeStatus === 'CLAIMED') { + return ; + } + + if (!token) { + return ; + } + + if (isPending) { + return ( + + + + ); + } + + if (data && !applyMode) { + return ; + } + + if (!data && typeStatus !== 'PENDING') { + return ; + } + + return ; +}; + +export const DvtApply: FC = () => ( + + + + + +); diff --git a/features/dvt/dvt-description-page.tsx b/features/dvt/dvt-description-page.tsx new file mode 100644 index 000000000..9d7616e61 --- /dev/null +++ b/features/dvt/dvt-description-page.tsx @@ -0,0 +1,34 @@ +import { FC } from 'react'; + +import { Layout } from 'shared/layout'; +import { DvtPageSwitcher } from 'shared/navigate'; +import { Faq, TypeBackButton } from 'shared/components'; +import { FAQ_OPERATOR_TYPE } from 'faq'; +import { BlockStyle } from './description/styles'; +import { + ApplicationFlow, + Introduction, + RequirementsCriteria, +} from './description'; +import { DvtApplyButton } from './apply-button'; +import { DvtProviders } from './shared'; + +export const DvtDescriptionPage: FC = () => ( + } + > + + + + + + + + + + + +); diff --git a/features/dvt/form-status/components/application.tsx b/features/dvt/form-status/components/application.tsx new file mode 100644 index 000000000..561fc340e --- /dev/null +++ b/features/dvt/form-status/components/application.tsx @@ -0,0 +1,141 @@ +import { Divider, Input, Text } from '@lidofinance/lido-ui'; +import { parseISO } from 'date-fns'; +import { DvtResponseDto } from 'features/dvt/shared'; +import { FC } from 'react'; +import { Address, InputAddress, Stack } from 'shared/components'; +import { VerifiedChip } from 'shared/components/input-address/verified-chip'; +import { formatDate } from 'utils'; +import { AccordionStyle, WrapperStyle } from '../styles'; + +type ApplicationProps = Pick; + +export const Application: FC = ({ + comments, + form, + createdAt, +}) => ( + + + Your application + + + Submitted {formatDate(parseISO(createdAt), 'dd.MM.yyyy')} + + + } + > + + + + + Main Address + + + + Main address{' '} + Verified + + } + value={form.mainAddress} + error={!!comments.mainAddress} + name="mainAddress" + /> + + {comments.mainAddress} + + + + + {form.discordLink || form.telegramUsername ? ( + + + Socials + + {form.discordLink && ( + + + + {comments.discordLink} + + + )} + {form.telegramUsername && ( + + + + {comments.telegramUsername} + + + )} + + ) : null} + + + + Cluster member addresses + + {form.clusterMembers.map((member, index) => ( + + + + Cluster member address #{index + 1} + + Verified + +
          + {member.discordHandle || member.telegramUsername ? ( + + {member.discordHandle && ( + + + Discord: + + {member.discordHandle} + + )} + {member.telegramUsername && ( + + + Telegram: + + {member.telegramUsername} + + )} + + ) : null} + {comments.clusterMembers?.[index] && ( + + {comments.clusterMembers[index]} + + )} + + ))} + + + +); diff --git a/features/dvt/form-status/components/index.ts b/features/dvt/form-status/components/index.ts new file mode 100644 index 000000000..fa4f20fad --- /dev/null +++ b/features/dvt/form-status/components/index.ts @@ -0,0 +1,2 @@ +export * from './status-header'; +export * from './application'; diff --git a/features/dvt/form-status/components/score-chip/index.ts b/features/dvt/form-status/components/score-chip/index.ts new file mode 100644 index 000000000..11e29b456 --- /dev/null +++ b/features/dvt/form-status/components/score-chip/index.ts @@ -0,0 +1 @@ +export * from './score-chip'; diff --git a/features/dvt/form-status/components/score-chip/score-chip.tsx b/features/dvt/form-status/components/score-chip/score-chip.tsx new file mode 100644 index 000000000..b2eae64dc --- /dev/null +++ b/features/dvt/form-status/components/score-chip/score-chip.tsx @@ -0,0 +1,25 @@ +import { FC, PropsWithChildren, ReactNode } from 'react'; +import { ChipStyle, Variants } from './style'; +import { Check, Close } from '@lidofinance/lido-ui'; +import { ReactComponent as Clock } from 'assets/icons/clock.svg'; + +type Props = { + type?: Variants; +}; + +const ICONS: Record = { + default: , + success: , + error: , + pending: , +}; + +export const ScoreChip: FC> = ({ + children, + type = 'default', +}) => ( + + {ICONS[type]} + {children} + +); diff --git a/features/dvt/form-status/components/score-chip/style.ts b/features/dvt/form-status/components/score-chip/style.ts new file mode 100644 index 000000000..44204386c --- /dev/null +++ b/features/dvt/form-status/components/score-chip/style.ts @@ -0,0 +1,37 @@ +import styled, { css } from 'styled-components'; + +export type Variants = keyof typeof variants; + +const variants = { + default: css` + color: var(--lido-color-text); + `, + success: css` + color: var(--lido-color-success); + `, + error: css` + color: var(--lido-color-error); + `, + pending: css` + color: var(--lido-color-textSecondary); + `, +}; + +export const ChipStyle = styled.div<{ $variant?: Variants }>` + display: flex; + flex-direction: row; + gap: ${({ theme }) => theme.spaceMap.xs}px; + + width: fit-content; + padding: 2px 12px; + align-items: center; + white-space: nowrap; + + border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px; + background: color-mix(in srgb, currentColor 15%, transparent); + + font-size: ${({ theme }) => theme.fontSizesMap.xs}px; + line-height: ${({ theme }) => theme.fontSizesMap.xl}px; + font-weight: 700; + ${(props) => variants[props.$variant || 'default']} +`; diff --git a/features/dvt/form-status/components/status-header.tsx b/features/dvt/form-status/components/status-header.tsx new file mode 100644 index 000000000..90bc45676 --- /dev/null +++ b/features/dvt/form-status/components/status-header.tsx @@ -0,0 +1,214 @@ +import { NodeOperatorId, OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Button, Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts'; +import { + DVT_ASSESSED_DATE, + DvtCommentsDto, + DvtFormStatus, + DvtTypeStatus, +} from 'features/dvt/shared'; +import { + NodeOperatorOwner, + useDappStatus, + useNodeOperatorId, + useOperatorOwner, +} from 'modules/web3'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { getOperatorTypeQuery } from 'shared/hooks'; +import { LocalLink } from 'shared/navigate'; +import { isAddressEqual } from 'viem'; +import { ScoreChip } from './score-chip'; + +type StatusHeaderProps = { + typeStatus: DvtTypeStatus; + status?: DvtFormStatus; + comments?: DvtCommentsDto; +}; + +const getStatus = ( + status: DvtFormStatus | undefined, + typeStatus: DvtTypeStatus, +) => { + switch (status) { + case 'APPROVED': + return ( + + Approved + + ); + case 'REJECTED': + return Rejected; + case 'REVIEW': + return Pending; + default: + return null; + } +}; + +const getProofStatus = (typeStatus: DvtTypeStatus) => { + switch (typeStatus) { + case 'CLAIMED': + return Claimed; + case 'ISSUED': + return Issued; + case 'OWNER_ISSUED': + return Approved; + default: + return Pending; + } +}; + +const useHint = ( + status: DvtFormStatus | undefined, + typeStatus: DvtTypeStatus, + comments: DvtCommentsDto | undefined, + owner: NodeOperatorOwner | undefined, + nodeOperatorId: NodeOperatorId | undefined, +) => { + switch (true) { + case typeStatus === 'CLAIMED': + return You successfully claimed your Operator type; + case typeStatus === 'ISSUED' && !!owner: + return ( + <> + + You're already eligible to claim IDVTC type + + + To claim your current address should be set as your Node Operator + owner. + + + ); + case typeStatus === 'ISSUED' && nodeOperatorId === undefined: + return ( + <> + + Create a new Node Operator with IDVTC operator type + + +
          + + + +
          + + ); + case typeStatus === 'ISSUED': + return ( + <> + + Claim your new operator type on the “Claim operator type” tab + + +
          + + + +
          + + ); + case typeStatus === 'OWNER_ISSUED': + return ( + <> + + Node Operator's owner address is already eligible to claim + IDVTC type + + + Connect with your Node Operator's owner address to claim IDVTC + type + + + ); + case status === 'REJECTED': + if (comments?.reason) { + return {comments.reason}; + } + return ( + + Your application was rejected by CSM committee. + {'\n'}If you believe that these address(es) were incorrectly flagged, + you may submit an appeal on the Lido Research Forum for review by the + CSM Committee. + + ); + case status === 'REVIEW': + return ( + + The application will be assessed after {DVT_ASSESSED_DATE} as of{' '} + {DVT_ASSESSED_DATE}. You cannot change the application while it is + being reviewed. + + ); + case status === 'APPROVED': + return ( + + Please await issuance; this process typically takes up to three weeks. + + ); + default: + return null; + } +}; + +export const StatusHeader: FC = ({ + status, + typeStatus, + comments, +}) => { + const { address } = useDappStatus(); + const nodeOperatorId = useNodeOperatorId(); + const { data: owner } = useOperatorOwner(nodeOperatorId); + + const otherOwner = + owner && address && !isAddressEqual(owner.address, address) + ? owner + : undefined; + + const statusChip = getStatus(status, typeStatus); + const proofChip = getProofStatus(typeStatus); + const hint = useHint( + status, + typeStatus, + comments, + otherOwner, + nodeOperatorId, + ); + + return ( + + {status && ( + + + Application + + {statusChip} + + )} + {(!status || status === 'APPROVED') && ( + + + Operator type + + {proofChip} + + )} + {hint} + + ); +}; diff --git a/features/dvt/form-status/form-status.tsx b/features/dvt/form-status/form-status.tsx new file mode 100644 index 000000000..3c39b8f8d --- /dev/null +++ b/features/dvt/form-status/form-status.tsx @@ -0,0 +1,44 @@ +import { Block, Button, Divider } from '@lidofinance/lido-ui'; +import { FC, useCallback } from 'react'; +import { Stack } from 'shared/components'; +import { DvtTypeStatus } from '../shared'; +import { DvtResponseDto } from '../shared/types'; +import { Application, StatusHeader } from './components'; + +type FormStatusProps = { + data: DvtResponseDto; + typeStatus: DvtTypeStatus; + reset: () => void; +}; + +export const FormStatus: FC = ({ + data, + typeStatus, + reset, +}) => { + const { status, form, comments, createdAt } = data; + + const handle = useCallback(() => { + window.scrollTo({ top: 0 }); + reset(); + }, [reset]); + + return ( + + + + + + {status === 'REJECTED' && ( + + )} + + + ); +}; diff --git a/features/dvt/form-status/proof-status.tsx b/features/dvt/form-status/proof-status.tsx new file mode 100644 index 000000000..d306f4118 --- /dev/null +++ b/features/dvt/form-status/proof-status.tsx @@ -0,0 +1,16 @@ +import { Block } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { DvtTypeStatus } from '../shared'; +import { StatusHeader } from './components'; + +type ProofStatusProps = { + typeStatus: DvtTypeStatus; +}; + +export const ProofStatus: FC = ({ typeStatus }) => { + return ( + + + + ); +}; diff --git a/features/dvt/form-status/styles.ts b/features/dvt/form-status/styles.ts new file mode 100644 index 000000000..93280d765 --- /dev/null +++ b/features/dvt/form-status/styles.ts @@ -0,0 +1,34 @@ +import styled from 'styled-components'; +import { Accordion } from '@lidofinance/lido-ui'; +import { Stack } from 'shared/components'; + +export const AccordionStyle = styled(Accordion)` + margin: 0; + + background: var(--lido-color-backgroundSecondary); + + & > div:first-child { + padding: 20px; + } + + & > div + div > div { + padding: 0 20px 20px 20px; + } + + p, + ul, + ol { + margin: 0; + } +`; + +export const WrapperStyle = styled(Stack).attrs({ + direction: 'column', + gap: 'sm', +})<{ $error?: boolean }>` + padding: ${({ theme }) => theme.spaceMap.md}px; + border-radius: ${({ theme }) => theme.borderRadiusesMap.lg}px; + border: 1px solid + ${({ $error }) => + $error ? 'var(--lido-color-error)' : 'var(--lido-color-border)'}; +`; diff --git a/features/dvt/index.ts b/features/dvt/index.ts new file mode 100644 index 000000000..97d69454e --- /dev/null +++ b/features/dvt/index.ts @@ -0,0 +1,2 @@ +export * from './dvt-description-page'; +export * from './dvt-apply-page'; diff --git a/features/dvt/shared/consts.ts b/features/dvt/shared/consts.ts new file mode 100644 index 000000000..c1c54224d --- /dev/null +++ b/features/dvt/shared/consts.ts @@ -0,0 +1 @@ +export const DVT_ASSESSED_DATE = 'June\u00A022nd'; diff --git a/features/dvt/shared/dvt-providers.tsx b/features/dvt/shared/dvt-providers.tsx new file mode 100644 index 000000000..ec8caff28 --- /dev/null +++ b/features/dvt/shared/dvt-providers.tsx @@ -0,0 +1,9 @@ +import { SurveysAuthProvider } from 'modules/surveys-sdk'; +import { FC, PropsWithChildren } from 'react'; +import { DvtStateProvider } from './dvt-state-provider'; + +export const DvtProviders: FC = ({ children }) => ( + + {children} + +); diff --git a/features/dvt/shared/dvt-state-provider.tsx b/features/dvt/shared/dvt-state-provider.tsx new file mode 100644 index 000000000..b6b9caaad --- /dev/null +++ b/features/dvt/shared/dvt-state-provider.tsx @@ -0,0 +1,95 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { + useIdvtcProof, + useNodeOperatorId, + useOperatorOwner, + useOperatorType, +} from 'modules/web3'; +import { endpoints, useSurveysQuery } from 'modules/surveys-sdk'; +import { + createContext, + FC, + PropsWithChildren, + useContext, + useMemo, + useState, +} from 'react'; +import invariant from 'tiny-invariant'; +import { DvtResponseDto } from './types'; + +export type DvtTypeStatus = 'PENDING' | 'ISSUED' | 'OWNER_ISSUED' | 'CLAIMED'; + +type DvtStateContextType = { + typeStatus: DvtTypeStatus; + data?: DvtResponseDto; + isPending: boolean; + isTypePending: boolean; + applyMode: boolean; + reset: (value?: boolean) => void; +}; + +const DvtStateContext = createContext( + {} as DvtStateContextType, +); + +export const useDvtState = () => { + const context = useContext(DvtStateContext); + invariant(context, 'Attempt to use `useDvtState` outside of provider'); + return context; +}; + +export const DvtStateProvider: FC = ({ children }) => { + const operatorId = useNodeOperatorId(); + const { data: operatorType } = useOperatorType(operatorId); + const { data: owner } = useOperatorOwner(operatorId); + + const { data: proofData, isPending: isTypePending } = useIdvtcProof(); + const { data: ownerProofData, isPending: isOwnerTypePending } = useIdvtcProof( + owner?.address, + ); + const { data, isPending } = useSurveysQuery( + endpoints.dvtStatus, + ); + + const [manualReset, setManualReset] = useState(false); + const applyMode = useMemo(() => manualReset || !data, [data, manualReset]); + + const typeStatus: DvtTypeStatus = useMemo(() => { + if (operatorType === OPERATOR_TYPE.CSM_IDVTC || proofData?.isConsumed) + return 'CLAIMED'; + if (proofData?.proof) return 'ISSUED'; + if (ownerProofData?.proof) return 'OWNER_ISSUED'; + return 'PENDING'; + }, [ + operatorType, + ownerProofData?.proof, + proofData?.isConsumed, + proofData?.proof, + ]); + + const value: DvtStateContextType = useMemo( + () => ({ + typeStatus, + data, + isPending, + isTypePending: isTypePending || (!!owner?.address && isOwnerTypePending), + applyMode, + reset: (value = true) => setManualReset(value), + }), + [ + typeStatus, + data, + isPending, + isTypePending, + owner?.address, + isOwnerTypePending, + applyMode, + ], + ); + + return ( + + {children} + + ); +}; diff --git a/features/dvt/shared/index.ts b/features/dvt/shared/index.ts new file mode 100644 index 000000000..1d8d718fc --- /dev/null +++ b/features/dvt/shared/index.ts @@ -0,0 +1,5 @@ +export * from './types'; +export * from './consts'; +export { DvtStateProvider, useDvtState } from './dvt-state-provider'; +export type { DvtTypeStatus } from './dvt-state-provider'; +export { DvtProviders } from './dvt-providers'; diff --git a/features/dvt/shared/types.ts b/features/dvt/shared/types.ts new file mode 100644 index 000000000..d84770b1b --- /dev/null +++ b/features/dvt/shared/types.ts @@ -0,0 +1,43 @@ +export type DvtFormStatus = 'APPROVED' | 'REJECTED' | 'REVIEW'; + +export type DvtClusterMemberDto = { + address: string; + signature: string; + discordHandle?: string; + telegramUsername?: string; +}; + +export type DvtApplyDto = { + mainAddress: string; + discordLink: string; + telegramUsername?: string; + clusterMembers: DvtClusterMemberDto[]; +}; + +export type DvtFormDataDto = { + mainAddress: string; + discordLink: string; + telegramUsername?: string; + clusterMembers: { + address: string; + discordHandle?: string; + telegramUsername?: string; + }[]; +}; + +export type DvtCommentsDto = { + reason?: string; + mainAddress?: string; + discordLink?: string; + telegramUsername?: string; + clusterMembers?: (string | null)[]; +}; + +export type DvtResponseDto = { + form: DvtFormDataDto; + status: DvtFormStatus; + issued: boolean; + comments: DvtCommentsDto; + createdAt: string; + updatedAt: string | null; +}; diff --git a/features/dvt/siwe-sign-in/siwe-sign-in.tsx b/features/dvt/siwe-sign-in/siwe-sign-in.tsx new file mode 100644 index 000000000..c9319ca26 --- /dev/null +++ b/features/dvt/siwe-sign-in/siwe-sign-in.tsx @@ -0,0 +1,42 @@ +import { Block, Button, Text } from '@lidofinance/lido-ui'; +import { useDappStatus } from 'modules/web3'; +import { FC } from 'react'; +import { InputAddress, Stack } from 'shared/components'; +import { useSiweAuth } from 'modules/siwe'; + +export const SiweSignIn: FC = () => { + const { address } = useDappStatus(); + const { signIn } = useSiweAuth(); + + return ( + + + + + Sign in + + + To continue, please sign a message with your connected address to + prove ownership. + + + + + You are requesting IDVTC operator type for the following address: + + + + + + + + ); +}; diff --git a/features/eject-keys/eject-keys-page.tsx b/features/eject-keys/eject-keys-page.tsx new file mode 100644 index 000000000..9856c0e0d --- /dev/null +++ b/features/eject-keys/eject-keys-page.tsx @@ -0,0 +1,26 @@ +import { FC } from 'react'; + +import { Layout } from 'shared/layout'; +import { + DeleteKeysSwitcher, + DeleteKeysSwitcherRoutes, + KeysPageSwitcher, +} from 'shared/navigate'; +import { EjectKeys } from './eject-keys'; +import { Faq, FormBlock } from 'shared/components'; +import { FAQ_KEYS } from 'faq'; + +export const EjectKeysPage: FC = () => ( + + + + + + + + +); diff --git a/features/eject-keys/eject-keys.tsx b/features/eject-keys/eject-keys.tsx new file mode 100644 index 000000000..2cb6517ef --- /dev/null +++ b/features/eject-keys/eject-keys.tsx @@ -0,0 +1,14 @@ +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; +import { EjectKeysForm } from './eject-keys/eject-keys-form'; + +export const EjectKeys = () => { + const key = useWeb3Key(); + return ( + <> + + + + + ); +}; diff --git a/features/eject-keys/eject-keys/confirm-eject-keys-modal.tsx b/features/eject-keys/eject-keys/confirm-eject-keys-modal.tsx new file mode 100644 index 000000000..7af4bf7dd --- /dev/null +++ b/features/eject-keys/eject-keys/confirm-eject-keys-modal.tsx @@ -0,0 +1,37 @@ +import { Button, Modal, Text } from '@lidofinance/lido-ui'; + +import type { ModalComponentType } from 'providers/modal-provider'; +import { Stack } from 'shared/components'; +import { ConfirmModalProps } from 'shared/hooks'; + +export const ConfirmEjectKeysModal: ModalComponentType = ({ + onConfirm, + onReject, + ...props +}) => { + return ( + + + + + Selected keys will be ejected from the Consensus Layer + + + Triggering the validator exit from the Execution Layer incurs + network fees and serves as a last resort measure to exit the + validator{' '} + + + Remember that validators exits don’t happen immediately and require + some time to be processed, and that the bond is only released once + the full withdrawal has been completed + + + + + + + ); +}; diff --git a/features/eject-keys/eject-keys/confirm-high-cost-modal.tsx b/features/eject-keys/eject-keys/confirm-high-cost-modal.tsx new file mode 100644 index 000000000..746158473 --- /dev/null +++ b/features/eject-keys/eject-keys/confirm-high-cost-modal.tsx @@ -0,0 +1,39 @@ +import { Button, Modal, Text } from '@lidofinance/lido-ui'; + +import type { ModalComponentType } from 'providers/modal-provider'; +import { Stack } from 'shared/components'; +import { ConfirmModalProps } from 'shared/hooks'; + +export const ConfirmHighCostModal: ModalComponentType = ({ + onConfirm, + onReject, + ...props +}) => { + return ( + + + + + High ejection cost detected + + + The ejection cost per key is unusually high. You may want to wait + for ejection fees to decrease. + + + Are you sure you want to proceed? + + + + + + + + + + ); +}; diff --git a/features/eject-keys/eject-keys/context/eject-keys-data-provider.tsx b/features/eject-keys/eject-keys/context/eject-keys-data-provider.tsx new file mode 100644 index 000000000..2dfd83328 --- /dev/null +++ b/features/eject-keys/eject-keys/context/eject-keys-data-provider.tsx @@ -0,0 +1,86 @@ +import { KEY_STATUS } from '@lidofinance/lido-csm-sdk'; +import { + KEY_OPERATOR_INFO, + KEY_OPERATOR_KEYS, + useEthereumBalance, + useKeyEjectFee, + useNodeOperatorId, + useOperatorCurveId, + useOperatorInfo, + useOperatorKeysWithStatus, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import { hasStatus } from 'utils'; +import { type EjectKeysFormNetworkData } from './types'; + +const useEjectKeysFormNetworkData: NetworkData< + EjectKeysFormNetworkData +> = () => { + const ethBalanceQuery = useEthereumBalance(); + const nodeOperatorId = useNodeOperatorId(); + const infoQuery = useOperatorInfo(nodeOperatorId); + const keysQuery = useOperatorKeysWithStatus(nodeOperatorId, (keys) => + keys.filter(hasStatus([KEY_STATUS.ACTIVE, KEY_STATUS.ACTIVATION_PENDING])), + ); + + const ethBalance = ethBalanceQuery.data; + const info = infoQuery.data; + const keys = keysQuery.data; + + const isEthBalanceLoading = ethBalanceQuery.isPending; + const isInfoLoading = infoQuery.isPending; + const isKeysLoading = keysQuery.isPending; + + const { data: curveId, isPending: isCurveIdLoading } = + useOperatorCurveId(nodeOperatorId); + const { data: ejectKeyFee, isPending: isEjectKeyFeeLoading } = + useKeyEjectFee(); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ + ethBalanceQuery.queryKey, + KEY_OPERATOR_INFO, + KEY_OPERATOR_KEYS, + ]); + }, [invalidate, ethBalanceQuery.queryKey]); + + const isPending = + isInfoLoading || + isCurveIdLoading || + isEthBalanceLoading || + isKeysLoading || + isEjectKeyFeeLoading; + + return { + data: { + ethBalance, + nodeOperatorId, + curveId, + ejectKeyFee, + keys, + info, + } as EjectKeysFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useEjectKeysFormData = useFormData; + +export const EjectKeysDataProvider: FC = ({ children }) => { + const networkData = useEjectKeysFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/eject-keys/eject-keys/context/eject-keys-form-provider.tsx b/features/eject-keys/eject-keys/context/eject-keys-form-provider.tsx new file mode 100644 index 000000000..8edc45b92 --- /dev/null +++ b/features/eject-keys/eject-keys/context/eject-keys-form-provider.tsx @@ -0,0 +1,31 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, +} from 'shared/hook-form/form-controller'; +import { EjectKeysUpdater } from './eject-keys-updater'; +import { type EjectKeysFormInputType } from './types'; +import { useEjectKeysFlowResolver } from './use-eject-keys-flow'; +import { useEjectKeysValidation } from './use-eject-keys-validation'; + +export const EjectKeysFormProvider: FC = ({ children }) => { + const resolver = useEjectKeysValidation(); + + const formObject = useForm({ + defaultValues: { selection: [] }, + resolver, + mode: 'onChange', + }); + + const submitter = useFlowSubmit(useEjectKeysFlowResolver()); + + return ( + + + + {children} + + + ); +}; diff --git a/features/eject-keys/eject-keys/context/eject-keys-updater.tsx b/features/eject-keys/eject-keys/context/eject-keys-updater.tsx new file mode 100644 index 000000000..55223c4e9 --- /dev/null +++ b/features/eject-keys/eject-keys/context/eject-keys-updater.tsx @@ -0,0 +1,27 @@ +import { FC, useEffect } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { useEjectKeysFormData } from './eject-keys-data-provider'; +import { EjectKeysFormInputType } from './types'; + +export const EjectKeysUpdater: FC = () => { + const [selection] = useWatch({ + name: ['selection'], + }); + + const { setValue } = useFormContext(); + + const { ejectKeyFee } = useEjectKeysFormData(); + + const feeAmount = + ejectKeyFee !== undefined && selection?.length + ? ejectKeyFee * BigInt(selection.length) + : undefined; + + useEffect(() => { + setValue('feeAmount', feeAmount, { shouldValidate: true }); + // setValue is stable ref and shouldn't be in deps + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [feeAmount]); + + return null; +}; diff --git a/features/eject-keys/eject-keys/context/index.ts b/features/eject-keys/eject-keys/context/index.ts new file mode 100644 index 000000000..adf032797 --- /dev/null +++ b/features/eject-keys/eject-keys/context/index.ts @@ -0,0 +1,4 @@ +export * from './eject-keys-form-provider'; +export * from './eject-keys-data-provider'; +export * from './types'; +export * from './use-eject-keys-flow'; diff --git a/features/eject-keys/eject-keys/context/types.ts b/features/eject-keys/eject-keys/context/types.ts new file mode 100644 index 000000000..ba14131fe --- /dev/null +++ b/features/eject-keys/eject-keys/context/types.ts @@ -0,0 +1,19 @@ +import { + KeyWithStatus, + NodeOperatorId, + NodeOperatorInfo, +} from '@lidofinance/lido-csm-sdk'; + +export type EjectKeysFormInputType = { + selection: number[]; + feeAmount?: bigint; +}; + +export type EjectKeysFormNetworkData = { + nodeOperatorId: NodeOperatorId; + curveId: bigint; + ethBalance: bigint; + keys: KeyWithStatus[]; + info: NodeOperatorInfo; + ejectKeyFee: bigint; +}; diff --git a/features/eject-keys/eject-keys/context/use-eject-keys-flow.ts b/features/eject-keys/eject-keys/context/use-eject-keys-flow.ts new file mode 100644 index 000000000..e20528dd8 --- /dev/null +++ b/features/eject-keys/eject-keys/context/use-eject-keys-flow.ts @@ -0,0 +1,77 @@ +import { type MethodAccess } from '@lidofinance/lido-csm-sdk'; +import { HIGH_EJECTION_COST_THRESHOLD } from 'consts'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useCanPerform } from 'shared/hooks'; +import { invariant } from '@lidofinance/lido-ethereum-sdk'; +import { useTxModalStagesEjectKeys } from '../hooks/use-tx-modal-stages-eject-keys'; +import { useConfirmHighCostModal } from '../hooks/use-confirm-high-cost-modal'; +import { useConfirmEjectKeysModal } from '../hooks/use-confirm-modal'; +import { useEjectKeysFormData } from './eject-keys-data-provider'; +import { EjectKeysFormInputType, EjectKeysFormNetworkData } from './types'; + +export type EjectKeysFlow = + | { action: 'no-access'; access: MethodAccess } + | { action: 'no-keys' } + | ({ action: 'eject' } & Executable); + +export const useEjectKeysFlowResolver = (): FlowResolver< + EjectKeysFormInputType, + EjectKeysFormNetworkData, + EjectKeysFlow +> => { + const { keys: keysSDK } = useSmSDK(); + const [canEjectKeys, access] = useCanPerform(keysSDK, 'ejectKeys'); + const confirmEject = useConfirmEjectKeysModal(); + const confirmHighCost = useConfirmHighCostModal(); + const buildCallback = useTxModalStagesEjectKeys(); + + return useCallback( + (input, data) => { + if (!canEjectKeys) return { action: 'no-access', access }; + if (!data.keys?.length) return { action: 'no-keys' }; + + return { + action: 'eject' as const, + confirm: async () => { + if ( + data.ejectKeyFee >= HIGH_EJECTION_COST_THRESHOLD && + !(await confirmHighCost({})) + ) { + return false; + } + + return confirmEject({}); + }, + submit: () => { + invariant(input.feeAmount !== undefined, 'Fee amount is required'); + + return keysSDK.ejectKeys({ + nodeOperatorId: data.nodeOperatorId, + keyIndices: input.selection.map(BigInt), + amount: input.feeAmount, + callback: buildCallback(input, data), + }); + }, + }; + }, + [ + keysSDK, + canEjectKeys, + access, + confirmEject, + confirmHighCost, + buildCallback, + ], + ); +}; + +export const useEjectKeysFlow = (): EjectKeysFlow => { + const resolve = useEjectKeysFlowResolver(); + const data = useEjectKeysFormData(true); + return resolve({} as EjectKeysFormInputType, data); +}; diff --git a/features/eject-keys/eject-keys/context/use-eject-keys-validation.ts b/features/eject-keys/eject-keys/context/use-eject-keys-validation.ts new file mode 100644 index 000000000..849c70068 --- /dev/null +++ b/features/eject-keys/eject-keys/context/use-eject-keys-validation.ts @@ -0,0 +1,18 @@ +import { + useFormValidation, + ValidationError, +} from 'shared/hook-form/validation'; +import type { EjectKeysFormInputType, EjectKeysFormNetworkData } from './types'; + +export const useEjectKeysValidation = () => { + return useFormValidation( + 'selection', + async ({ selection }, _, validate) => { + await validate('selection', () => { + if (selection?.length === 0) { + throw new ValidationError('selection', 'No keys selected'); + } + }); + }, + ); +}; diff --git a/features/eject-keys/eject-keys/controls/amount-input.tsx b/features/eject-keys/eject-keys/controls/amount-input.tsx new file mode 100644 index 000000000..6b3402899 --- /dev/null +++ b/features/eject-keys/eject-keys/controls/amount-input.tsx @@ -0,0 +1,29 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { useWatch } from 'react-hook-form'; +import { DisabledInputAmount, IconTooltip, Stack } from 'shared/components'; +import { EjectKeysFormInputType } from '../context'; + +export const AmountInput = () => { + const { feeAmount } = useWatch(); + + return ( + + + + Will be deducted from your wallet balance{' '} + + + + ); +}; diff --git a/features/eject-keys/eject-keys/controls/keys-selector.tsx b/features/eject-keys/eject-keys/controls/keys-selector.tsx new file mode 100644 index 000000000..b5f3a82c5 --- /dev/null +++ b/features/eject-keys/eject-keys/controls/keys-selector.tsx @@ -0,0 +1,30 @@ +import { isModuleCM, PATH } from 'consts'; +import { FormTitle, WarningBlock } from 'shared/components'; +import { EjectKeysSelectorHookForm } from 'shared/hook-form/controls'; +import { LocalLink } from 'shared/navigate'; +import { useEjectKeysFormData } from '../context'; + +export const KeysSelector = () => { + const { keys } = useEjectKeysFormData(true); + + return ( + <> + + This is not the normal exit flow. This functionality should be + used only as a last resort to exit your keys by utilizing the Execution + Layer Triggerable Withdrawals (which includes additional network fees). + You might need to use this method in case you don’t have an ability to + access your validator keys. If you can exit your keys normally, please + proceed with{' '} + {isModuleCM ? ( + 'the regular exit flow' + ) : ( + the regular exit flow + )} + . + + Choose keys to eject + + + ); +}; diff --git a/features/eject-keys/eject-keys/controls/submit-button.tsx b/features/eject-keys/eject-keys/controls/submit-button.tsx new file mode 100644 index 000000000..b7f19ec09 --- /dev/null +++ b/features/eject-keys/eject-keys/controls/submit-button.tsx @@ -0,0 +1,5 @@ +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; + +export const SubmitButton = () => { + return Eject Keys; +}; diff --git a/features/eject-keys/eject-keys/eject-keys-form-info.tsx b/features/eject-keys/eject-keys/eject-keys-form-info.tsx new file mode 100644 index 000000000..e04c2e031 --- /dev/null +++ b/features/eject-keys/eject-keys/eject-keys-form-info.tsx @@ -0,0 +1,23 @@ +import { DataTable, DataTableRow } from '@lidofinance/lido-ui'; +import { useWatch } from 'react-hook-form'; +import { EjectKeysFormInputType, useEjectKeysFormData } from './context'; +import { FormatToken } from 'shared/formatters'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; + +export const EjectKeysFormInfo = () => { + const selection = useWatch({ + name: 'selection', + }); + const { ejectKeyFee } = useEjectKeysFormData(); + + return ( + + + {selection.length} + + + + + + ); +}; diff --git a/features/eject-keys/eject-keys/eject-keys-form-loader.tsx b/features/eject-keys/eject-keys/eject-keys-form-loader.tsx new file mode 100644 index 000000000..7f3492323 --- /dev/null +++ b/features/eject-keys/eject-keys/eject-keys-form-loader.tsx @@ -0,0 +1,28 @@ +import { FC, PropsWithChildren } from 'react'; +import { EmptyState, NoAccessNotice } from 'shared/components'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useEjectKeysFlow } from './context'; + +const EjectKeysFormGate: FC = ({ children }) => { + const flow = useEjectKeysFlow(); + + if (flow.action === 'no-access') { + return ; + } + + if (flow.action === 'no-keys') { + return ( + + No keys available to eject + + ); + } + + return <>{children}; +}; + +export const EjectKeysFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/eject-keys/eject-keys/eject-keys-form.tsx b/features/eject-keys/eject-keys/eject-keys-form.tsx new file mode 100644 index 000000000..770ffb835 --- /dev/null +++ b/features/eject-keys/eject-keys/eject-keys-form.tsx @@ -0,0 +1,28 @@ +import { FC, memo } from 'react'; +import { FormBlock } from 'shared/components'; +import { Form } from 'shared/hook-form/form-controller'; +import { EjectKeysDataProvider, EjectKeysFormProvider } from './context'; +import { AmountInput } from './controls/amount-input'; +import { KeysSelector } from './controls/keys-selector'; +import { SubmitButton } from './controls/submit-button'; +import { EjectKeysFormInfo } from './eject-keys-form-info'; +import { EjectKeysFormLoader } from './eject-keys-form-loader'; + +export const EjectKeysForm: FC = memo(() => { + return ( + + + + +
          + + + + + +
          +
          +
          +
          + ); +}); diff --git a/features/eject-keys/eject-keys/hooks/use-confirm-high-cost-modal.ts b/features/eject-keys/eject-keys/hooks/use-confirm-high-cost-modal.ts new file mode 100644 index 000000000..0ba02eabc --- /dev/null +++ b/features/eject-keys/eject-keys/hooks/use-confirm-high-cost-modal.ts @@ -0,0 +1,4 @@ +import { getUseConfirmModal } from 'shared/hooks'; +import { ConfirmHighCostModal } from '../confirm-high-cost-modal'; + +export const useConfirmHighCostModal = getUseConfirmModal(ConfirmHighCostModal); diff --git a/features/eject-keys/eject-keys/hooks/use-confirm-modal.ts b/features/eject-keys/eject-keys/hooks/use-confirm-modal.ts new file mode 100644 index 000000000..ca6140db6 --- /dev/null +++ b/features/eject-keys/eject-keys/hooks/use-confirm-modal.ts @@ -0,0 +1,6 @@ +import { getUseConfirmModal } from 'shared/hooks'; +import { ConfirmEjectKeysModal } from '../confirm-eject-keys-modal'; + +export const useConfirmEjectKeysModal = getUseConfirmModal( + ConfirmEjectKeysModal, +); diff --git a/features/eject-keys/eject-keys/hooks/use-tx-modal-stages-eject-keys.tsx b/features/eject-keys/eject-keys/hooks/use-tx-modal-stages-eject-keys.tsx new file mode 100644 index 000000000..8e1d8eee4 --- /dev/null +++ b/features/eject-keys/eject-keys/hooks/use-tx-modal-stages-eject-keys.tsx @@ -0,0 +1,49 @@ +import { Plural } from 'shared/components'; +import { + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import { + EjectKeysFormInputType, + EjectKeysFormNetworkData, +} from '../context/types'; + +export const useTxModalStagesEjectKeys = () => + useTxStages( + (transitStage, input) => ({ + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (_result: undefined, txHash) => + transitStage( + + {input.selection.length}{' '} + {' '} + ejected + + } + description="" + />, + ), + }), + ); diff --git a/features/eject-keys/eject-keys/index.ts b/features/eject-keys/eject-keys/index.ts new file mode 100644 index 000000000..dd468defe --- /dev/null +++ b/features/eject-keys/eject-keys/index.ts @@ -0,0 +1 @@ +export { EjectKeysForm } from './eject-keys-form'; diff --git a/features/eject-keys/index.ts b/features/eject-keys/index.ts new file mode 100644 index 000000000..04001a792 --- /dev/null +++ b/features/eject-keys/index.ts @@ -0,0 +1,2 @@ +export * from './eject-keys-page'; +export * from './eject-keys'; diff --git a/features/exit-keys/exit-keys-page.tsx b/features/exit-keys/exit-keys-page.tsx new file mode 100644 index 000000000..c68945d99 --- /dev/null +++ b/features/exit-keys/exit-keys-page.tsx @@ -0,0 +1,26 @@ +import { FC } from 'react'; + +import { Layout } from 'shared/layout'; +import { + DeleteKeysSwitcher, + DeleteKeysSwitcherRoutes, + KeysPageSwitcher, +} from 'shared/navigate'; +import { ExitKeys } from './exit-keys'; +import { Faq, FormBlock } from 'shared/components'; +import { FAQ_KEYS } from 'faq'; + +export const ExitKeysPage: FC = () => ( + + + + + + + + +); diff --git a/features/exit-keys/exit-keys.tsx b/features/exit-keys/exit-keys.tsx new file mode 100644 index 000000000..7a3bab6c1 --- /dev/null +++ b/features/exit-keys/exit-keys.tsx @@ -0,0 +1,105 @@ +import { Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { moduleMeta } from 'consts/module'; +import { + FormTitle, + MatomoLink, + StackStyle, + WarningBlock, +} from 'shared/components'; +import { Gate } from 'shared/navigate'; + +export const ExitKeys = () => { + return ( + <> + + Follow the instuctions + + Sign and broadcast an exit message for each validator key you want to + exit using one of the guides below: + + +
        • + + Guide for Dappnode + +
        • +
        • + + Guide for Sedge + +
        • +
        • + + Guide for Stereum + +
        • +
        • + + Guide for EthPillar + +
        • +
        • + + Guide for EthDocker + +
        • +
        • + + Guide for Systemd + +
        • +
          +
          + + + Out of order exits are discouraged by{' '} + + the Validator Exits Standard Node Operator Protocol (SNOP) + + . In case an out of order exit is required, the Node Operator must + notify the community, specifying the number of validators affected, + their indices, and the reason for the exit request via{' '} + + the Node Operator category of the Lido Research Forum + + . + + + + This action should be performed{' '} + outside the {moduleMeta.shortName} UI + + + ); +}; diff --git a/features/exit-keys/index.ts b/features/exit-keys/index.ts new file mode 100644 index 000000000..1939d3244 --- /dev/null +++ b/features/exit-keys/index.ts @@ -0,0 +1,2 @@ +export * from './exit-keys-page'; +export * from './exit-keys'; diff --git a/features/group/group-page.tsx b/features/group/group-page.tsx new file mode 100644 index 000000000..1f339ead7 --- /dev/null +++ b/features/group/group-page.tsx @@ -0,0 +1,44 @@ +import { + useNodeOperatorId, + useOperatorGroup, + useOperatorGroupId, +} from 'modules/web3'; +import { FC } from 'react'; +import { Layout } from 'shared/layout'; +import { Group } from './group'; +import { BackButton, ShortInlineLoader } from 'shared/components'; +import { formatGroupTitle } from 'shared/node-operator'; + +export const GroupPage: FC = () => ( + } + title={} + subtitle={} + pageName="Group" + > + + +); + +const GroupTitle: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: group, isPending } = useOperatorGroup(nodeOperatorId); + + return isPending ? ( + + ) : group ? ( + <>{formatGroupTitle(group)} + ) : ( + <>No group attached to operator + ); +}; + +const GroupSubtitle: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: groupId } = useOperatorGroupId(nodeOperatorId); + + return groupId ? ( + <>View all of the sub-operators within your Node Operator Group + ) : null; +}; diff --git a/features/group/group-summary.tsx b/features/group/group-summary.tsx new file mode 100644 index 000000000..4b71a0f7c --- /dev/null +++ b/features/group/group-summary.tsx @@ -0,0 +1,46 @@ +import { SubOperatorStakeSummary } from '@lidofinance/lido-csm-sdk'; +import { InlineLoader, Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { MoreKeysChip, StakeRow, StakeStats } from './shared'; +import { WeightChip } from './shared/weight-chip'; +import { CardHeader, CardHeaderLeft, GroupBlockStyled } from './styles'; +import { useAggregatedStake } from './use-aggregated-stake'; + +type Props = { + operators: SubOperatorStakeSummary[]; +}; + +export const GroupSummary: FC = ({ operators }) => { + const { aggregated, totalWeight, moreKeys, isPending } = + useAggregatedStake(operators); + + return ( + + + + + + Group summary + + + + + + + {!aggregated ? ( + + + + ) : ( + + )} + + + ); +}; diff --git a/features/group/group.tsx b/features/group/group.tsx new file mode 100644 index 000000000..600a8d901 --- /dev/null +++ b/features/group/group.tsx @@ -0,0 +1,25 @@ +import { useNodeOperatorId, useOperatorGroupStakeSummary } from 'modules/web3'; +import { FC } from 'react'; +import { WhenLoaded } from 'shared/components'; +import { GroupSummary } from './group-summary'; +import { GroupGrid } from './styles'; +import { OperatorCard } from './operator-card'; + +export const Group: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data, isPending } = useOperatorGroupStakeSummary(nodeOperatorId); + + return ( + No Group}> + + + {data?.operators.map((stakeSummary) => ( + + ))} + + + ); +}; diff --git a/features/group/index.ts b/features/group/index.ts new file mode 100644 index 000000000..64af8fe9a --- /dev/null +++ b/features/group/index.ts @@ -0,0 +1 @@ +export { GroupPage } from './group-page'; diff --git a/features/group/operator-card/index.ts b/features/group/operator-card/index.ts new file mode 100644 index 000000000..d6bef227f --- /dev/null +++ b/features/group/operator-card/index.ts @@ -0,0 +1 @@ +export * from './operator-card'; diff --git a/features/group/operator-card/operator-card-actions.tsx b/features/group/operator-card/operator-card-actions.tsx new file mode 100644 index 000000000..039da935b --- /dev/null +++ b/features/group/operator-card/operator-card-actions.tsx @@ -0,0 +1,95 @@ +import { NodeOperatorId, NodeOperatorInfo } from '@lidofinance/lido-csm-sdk'; +import { Button, Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { PATH } from 'consts/urls'; +import { useNodeOperator } from 'modules/web3'; +import { useDappStatus } from 'modules/web3/hooks/use-dapp-status'; +import { FC, useCallback } from 'react'; +import { LocalLink } from 'shared/navigate'; +import { useOpenOperatorSwitchModal } from 'shared/node-operator/switch-modal'; +import { trackMatomoEvent } from 'utils'; +import { isAddressEqual } from 'viem'; + +type Props = { + nodeOperatorId: NodeOperatorId; + info: NodeOperatorInfo | undefined; + moreKeys: boolean; +}; + +export const OperatorCardActions: FC = ({ + nodeOperatorId, + info, + moreKeys, +}) => { + const { nodeOperator } = useNodeOperator(); + const { address } = useDappStatus(); + const openModal = useOpenOperatorSwitchModal(PATH.HOME); + + const handleOpenSwitchModal = useCallback(() => { + trackMatomoEvent(MATOMO_CLICK_EVENTS_TYPES.groupSwitchOperator); + openModal(); + }, [openModal]); + + const isCurrentOperator = nodeOperator?.nodeOperatorId === nodeOperatorId; + + const isManagerByCurrentWallet = + !!address && !!info && isAddressEqual(info.managerAddress, address); + + const isRewardsByCurrentWallet = + !!address && !!info && isAddressEqual(info.rewardsAddress, address); + + if (isCurrentOperator) { + if (isManagerByCurrentWallet) { + return ( + + + + ); + } + return null; + } + + if (isManagerByCurrentWallet && moreKeys) { + return ( + + ); + } + + if (isManagerByCurrentWallet || isRewardsByCurrentWallet) { + return ( + + ); + } + + return ( + + ); +}; diff --git a/features/group/operator-card/operator-card.tsx b/features/group/operator-card/operator-card.tsx new file mode 100644 index 000000000..593190d9d --- /dev/null +++ b/features/group/operator-card/operator-card.tsx @@ -0,0 +1,136 @@ +import { + NodeOperatorInfo, + OperatorMetadata, + SubOperatorStakeSummary, +} from '@lidofinance/lido-csm-sdk'; +import { Block, InlineLoader, Text } from '@lidofinance/lido-ui'; +import { + useOperatorCurveId, + useOperatorInfo, + useOperatorMetadata, +} from 'modules/web3'; +import { FC, useMemo } from 'react'; +import { Address, Stack } from 'shared/components'; +import { useCurveMetadata } from 'shared/hooks'; +import { DescriptorId } from 'shared/node-operator'; +import { computeStakeData, StakeAndKeysData } from 'utils'; +import { KeyLimit, MoreKeysChip, StakeStats } from '../shared'; +import { WeightChip } from '../shared/weight-chip'; +import { DividerStyled } from '../styles'; +import { OperatorCardActions } from './operator-card-actions'; + +export const OperatorCard: FC = ({ + nodeOperatorId, + ...props +}) => { + const { data: metadata } = useOperatorMetadata(nodeOperatorId); + const { data: info } = useOperatorInfo(nodeOperatorId); + const { data: curveId } = useOperatorCurveId(nodeOperatorId); + + const stakeAndKeys = useMemo( + () => (info ? computeStakeData(props, info) : undefined), + [info, props], + ); + + const moreKeys = !!stakeAndKeys?.potentialAdditionalKeys; + + return ( + + + + + + + + + ); +}; + +const OperatorCardHeader: FC< + SubOperatorStakeSummary & { + operatorMetadata?: OperatorMetadata; + info?: NodeOperatorInfo; + curveId: bigint | undefined; + stakeAndKeys: StakeAndKeysData | undefined; + } +> = ({ + nodeOperatorId, + weight, + operatorMetadata, + info, + curveId, + stakeAndKeys, +}) => { + const curveMetadata = useCurveMetadata(curveId); + + return ( + + + + + + + + + + {info && ( + + )} + + + {operatorMetadata && info && curveId !== undefined ? ( + + + {operatorMetadata.name} + + + + {curveMetadata?.name} + + + ) : ( + + )} + + {info ? ( + + + Rewards:{' '} +
          + + + + Manager:{' '} +
          + + + ) : ( + + )} + + ); +}; diff --git a/features/group/shared/index.ts b/features/group/shared/index.ts new file mode 100644 index 000000000..4ebfd05f2 --- /dev/null +++ b/features/group/shared/index.ts @@ -0,0 +1,10 @@ +export { StakeStats, STAKE_COLORS } from './stake-stats'; +export { KeyLimit } from './key-limit'; +export { MoreKeysChip } from './more-keys-chip'; +export { + StakeRow, + StakeColumn, + ColorDot, + StakeBar, + StakeBarSegment, +} from './styles'; diff --git a/features/group/shared/key-limit.tsx b/features/group/shared/key-limit.tsx new file mode 100644 index 000000000..2ada9e165 --- /dev/null +++ b/features/group/shared/key-limit.tsx @@ -0,0 +1,25 @@ +import { NodeOperatorInfo } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { pluralKeys } from 'utils'; + +type Props = { + info: NodeOperatorInfo | undefined; +}; + +export const KeyLimit: FC = ({ info }) => { + if (!info?.targetLimit) return null; + + const keys = info.totalAddedKeys - info.totalWithdrawnKeys; + const limitText = pluralKeys({ value: info.targetLimit, showValue: true }); + + return ( + + {info.targetLimit <= keys ? ( + <>Key limit of {limitText} has been reached + ) : ( + <>Key limit to this Node Operator is set to {limitText} + )} + + ); +}; diff --git a/features/group/shared/more-keys-chip.tsx b/features/group/shared/more-keys-chip.tsx new file mode 100644 index 000000000..46514c455 --- /dev/null +++ b/features/group/shared/more-keys-chip.tsx @@ -0,0 +1,32 @@ +import { FC } from 'react'; +import { SquaredChip } from 'shared/components'; +import { Alert, Check } from 'features/dashboard/keys/keys-breakdown/styles'; + +type Props = { + more: boolean; + empty?: boolean; + isPending?: boolean; +}; + +export const MoreKeysChip: FC = ({ more, empty, isPending }) => { + if (isPending) return null; + + return ( + + {more ? ( + <> + + {empty ? 'Upload keys' : 'Upload more keys'} + + ) : ( + <> + + Enough keys + + )} + + ); +}; diff --git a/features/group/shared/stake-stats.tsx b/features/group/shared/stake-stats.tsx new file mode 100644 index 000000000..f50e8f209 --- /dev/null +++ b/features/group/shared/stake-stats.tsx @@ -0,0 +1,125 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { IconTooltip, Stack } from 'shared/components'; +import { FormatToken } from 'shared/formatters'; +import { getPercent, pluralKeys, StakeAndKeysData } from 'utils'; +import { + ColorDot, + StakeBar, + StakeBarSegment, + StakeColumn, + StakeRow, +} from './styles'; + +export const STAKE_COLORS = { + active: '#53ba95', + depositable: '#00a3ff', + potential: '#b8bcc1', +} as const; + +type Props = { + data?: StakeAndKeysData; +}; + +export const StakeStats: FC = ({ data }) => { + if (!data) return null; + + const totalStake = + data.activeStake + data.depositableStake + data.potentialAdditionalStake; + + return ( + + + + + + Active + + + + + + + + {pluralKeys({ value: data.activeKeys, showValue: true })} + + + + + + + + Depositable + + + + + + + + {pluralKeys({ value: data.depositableKeys, showValue: true })} + + + + + + + + Potential additional capacity + + + + + + + + {pluralKeys({ + value: data.potentialAdditionalKeys, + showValue: true, + })} + + + + + + + + + + + + ); +}; diff --git a/features/group/shared/styles.ts b/features/group/shared/styles.ts new file mode 100644 index 000000000..acd962961 --- /dev/null +++ b/features/group/shared/styles.ts @@ -0,0 +1,50 @@ +import styled from 'styled-components'; + +export const StakeRow = styled.div` + padding: 12px 16px; + display: flex; + gap: 12px; + + ${({ theme }) => theme.mediaQueries.lg} { + flex-direction: column; + } +`; + +export const StakeColumn = styled.div` + min-width: 20%; + flex: 1 0 auto; + display: flex; + flex-direction: column; + gap: 4px; +`; + +export const ColorDot = styled.span<{ $color: string }>` + display: inline-block; + width: 12px; + height: 12px; + border-radius: 50%; + background: ${({ $color }) => $color}; + flex-shrink: 0; +`; + +export const StakeBar = styled.div` + display: flex; + gap: 1px; + height: ${({ theme }) => theme.spaceMap.md}px; + width: 100%; + border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px; + background: var(--lido-color-backgroundSecondary); + overflow: hidden; + white-space: nowrap; +`; + +export const StakeBarSegment = styled.div<{ + $color: string; + $width: number; +}>` + height: 100%; + width: ${({ $width }) => $width}%; + background: ${({ $color }) => $color}; + transition: width 0.25s ease-in-out; + display: ${({ $width }) => ($width <= 0 ? 'none' : 'block')}; +`; diff --git a/features/group/shared/weight-chip.tsx b/features/group/shared/weight-chip.tsx new file mode 100644 index 000000000..38bf38b79 --- /dev/null +++ b/features/group/shared/weight-chip.tsx @@ -0,0 +1,11 @@ +import { FC } from 'react'; +import { ChipProps, SquaredChip } from 'shared/components'; +import { formatBP } from 'utils'; + +export const WeightChip: FC = ({ + weight, + ...props +}) => + weight !== undefined ? ( + Weight: {formatBP(weight)} + ) : null; diff --git a/features/group/styles.ts b/features/group/styles.ts new file mode 100644 index 000000000..bb659f5d8 --- /dev/null +++ b/features/group/styles.ts @@ -0,0 +1,66 @@ +import { Divider } from '@lidofinance/lido-ui'; +import { Block } from 'shared/components'; +import styled from 'styled-components'; + +export const GroupGrid = styled.div` + display: grid; + grid-template-columns: 1fr 1fr; + gap: ${({ theme }) => theme.spaceMap.xl}px; + + > :first-child { + grid-column: 1 / -1; + } + + &:not(:has(> :nth-child(3))) { + grid-template-columns: 1fr; + max-width: var(--layout-base-width); + } + + ${({ theme }) => theme.mediaQueries.xl} { + grid-template-columns: 1fr; + } +`; + +export const CardHeader = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + gap: ${({ theme }) => theme.spaceMap.sm}px; +`; + +export const CardHeaderLeft = styled.div` + display: flex; + align-items: center; + gap: ${({ theme }) => theme.spaceMap.sm}px; + min-width: 0; +`; + +export const CardSubheader = styled.div` + display: flex; + align-items: center; + gap: ${({ theme }) => theme.spaceMap.xs}px; + color: var(--lido-color-textSecondary); + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; +`; + +export const AddressRow = styled.div` + display: flex; + align-items: center; + gap: ${({ theme }) => theme.spaceMap.sm}px; + color: var(--lido-color-textSecondary); + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; +`; + +export const KeyLimitText = styled.p` + color: var(--lido-color-textSecondary); + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; + text-align: center; +`; + +export const DividerStyled = styled(Divider).attrs({ type: 'vertical' })` + opacity: 0.3; +`; + +export const GroupBlockStyled = styled(Block)` + outline: 1px solid var(--lido-color-border); +`; diff --git a/features/group/use-aggregated-stake.ts b/features/group/use-aggregated-stake.ts new file mode 100644 index 000000000..8b7c59385 --- /dev/null +++ b/features/group/use-aggregated-stake.ts @@ -0,0 +1,69 @@ +import { SubOperatorStakeSummary } from '@lidofinance/lido-csm-sdk'; +import { useQueries } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useMemo } from 'react'; +import { useSmSDK } from 'modules/web3/web3-provider'; +import { KEY_OPERATOR_INFO } from 'modules/web3/hooks/use-operator-info'; +import { computeStakeData, StakeAndKeysData } from 'utils'; + +export const useAggregatedStake = (operators: SubOperatorStakeSummary[]) => { + const { operator } = useSmSDK(); + + const infoQueries = useQueries({ + queries: operators.map((op) => ({ + queryKey: [...KEY_OPERATOR_INFO, { nodeOperatorId: op.nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: () => operator.getInfo(op.nodeOperatorId), + })), + }); + + const isPending = infoQueries.some((q) => q.isPending); + const infoUpdatedAt = infoQueries.map((q) => q.dataUpdatedAt).join(','); + + const { aggregated, totalWeight } = useMemo(() => { + if (isPending) return { aggregated: undefined, totalWeight: undefined }; + + const items = operators.map((op, i) => { + const info = infoQueries[i]?.data; + if (!info) return undefined; + return computeStakeData(op, info); + }); + + const defined = items.filter( + (item): item is StakeAndKeysData => item !== undefined, + ); + if (defined.length !== items.length) { + return { aggregated: undefined, totalWeight: undefined }; + } + + const agg = defined.reduce( + (acc, item) => ({ + activeStake: acc.activeStake + item.activeStake, + activeKeys: acc.activeKeys + item.activeKeys, + depositableStake: acc.depositableStake + item.depositableStake, + depositableKeys: acc.depositableKeys + item.depositableKeys, + potentialAdditionalStake: + acc.potentialAdditionalStake + item.potentialAdditionalStake, + potentialAdditionalKeys: + acc.potentialAdditionalKeys + item.potentialAdditionalKeys, + }), + { + activeStake: 0n, + activeKeys: 0, + depositableStake: 0n, + depositableKeys: 0, + potentialAdditionalStake: 0n, + potentialAdditionalKeys: 0, + }, + ); + + const weight = operators.reduce((sum, op) => sum + op.weight, 0n); + + return { aggregated: agg, totalWeight: weight }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isPending, infoUpdatedAt]); + + const moreKeys = aggregated ? aggregated.potentialAdditionalKeys > 0 : false; + + return { aggregated, totalWeight, moreKeys, isPending }; +}; diff --git a/features/ics/apply-button.tsx b/features/ics/apply-button.tsx new file mode 100644 index 000000000..adaccd83a --- /dev/null +++ b/features/ics/apply-button.tsx @@ -0,0 +1,84 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Button, ButtonProps } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { useNodeOperatorId } from 'modules/web3'; +import { FC } from 'react'; +import { getOperatorTypeQuery } from 'shared/hooks'; +import { LocalLink } from 'shared/navigate'; +import { IcsFormStatus, TypeStatus, useIcsState } from './shared'; + +type ButtonState = { + text: string; + variant: ButtonProps['variant']; + href: PATH; + query?: Record; +}; + +const getButtonState = ( + typeStatus: TypeStatus, + status: IcsFormStatus | undefined, + hasOperator: boolean, +): ButtonState => { + if (typeStatus === 'CLAIMED') { + return { + text: 'View ICS status', + variant: 'translucent', + href: PATH.TYPE_ICS_APPLY, + }; + } + if (typeStatus === 'ISSUED') { + // Claiming a type writes onto an existing operator, so without an + // active one the only meaningful action is to create it. + if (!hasOperator) { + return { + text: 'Create ICS operator', + variant: undefined, + href: PATH.CREATE, + query: getOperatorTypeQuery(OPERATOR_TYPE.CSM_ICS), + }; + } + return { + text: 'Claim ICS type', + variant: undefined, + href: PATH.TYPE_ICS_CLAIM, + }; + } + switch (status) { + case 'APPROVED': + case 'REJECTED': + case 'REVIEW': + return { + text: 'View application', + variant: 'translucent', + href: PATH.TYPE_ICS_APPLY, + }; + default: + return { + text: 'Apply for ICS', + variant: 'translucent', + href: PATH.TYPE_ICS_APPLY, + }; + } +}; + +type Props = { + size?: ButtonProps['size']; +}; + +export const IcsApplyButton: FC = ({ size }) => { + const { typeStatus, data } = useIcsState(); + const nodeOperatorId = useNodeOperatorId(); + const { text, variant, href, query } = getButtonState( + typeStatus, + data?.status, + nodeOperatorId !== undefined, + ); + + return ( + + + + ); +}; diff --git a/features/ics/apply-form/apply-form.tsx b/features/ics/apply-form/apply-form.tsx new file mode 100644 index 000000000..9fab1acd0 --- /dev/null +++ b/features/ics/apply-form/apply-form.tsx @@ -0,0 +1,27 @@ +import { FC, memo } from 'react'; +import { FormBlock } from 'shared/components'; +import { FormLoader, Form } from 'shared/hook-form/form-controller'; +import { ApplyDataProvider, ApplyFormProvider } from './context'; +import { + AdditionalAddresses, + MainAddress, + SocialProof, + SubmitButton, +} from './controls'; + +export const ApplyForm: FC = memo(() => ( + + + + +
          + + + + + +
          +
          +
          +
          +)); diff --git a/features/ics/apply-form/context/apply-data-provider.tsx b/features/ics/apply-form/context/apply-data-provider.tsx new file mode 100644 index 000000000..a5e05a31b --- /dev/null +++ b/features/ics/apply-form/context/apply-data-provider.tsx @@ -0,0 +1,40 @@ +import { useQueryClient } from '@tanstack/react-query'; +import { surveysKeys } from 'modules/surveys-sdk'; +import { useDappStatus } from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import type { ApplyFormNetworkData } from './types'; + +const useApplyFormNetworkData: NetworkData = () => { + const { address } = useDappStatus(); + + const queryClient = useQueryClient(); + + const revalidate = useCallback(() => { + void queryClient.invalidateQueries({ queryKey: surveysKeys.auth }); + }, [queryClient]); + + return { + data: { + mainAddress: address, + } as ApplyFormNetworkData, + isPending: false, + revalidate, + }; +}; + +export const useApplyFormData = useFormData; + +export const ApplyDataProvider: FC = ({ children }) => { + const networkData = useApplyFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/ics/apply-form/context/apply-form-provider.tsx b/features/ics/apply-form/context/apply-form-provider.tsx new file mode 100644 index 000000000..36ff70cfb --- /dev/null +++ b/features/ics/apply-form/context/apply-form-provider.tsx @@ -0,0 +1,36 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, + useFormDefaultValues, +} from 'shared/hook-form/form-controller'; +import type { ApplyFormInputType } from './types'; +import { useApplyFlowResolver } from './use-apply-flow'; +import { useApplyFormValidation } from './use-apply-form-validation'; + +export const ApplyFormProvider: FC = ({ children }) => { + const resolver = useApplyFormValidation(); + + const defaultValues = useFormDefaultValues(() => ({ + additionalAddresses: [], + twitterLink: '', + discordLink: '', + })); + + const formObject = useForm({ + defaultValues, + resolver, + mode: 'onChange', + }); + + const submitter = useFlowSubmit(useApplyFlowResolver()); + + return ( + + + {children} + + + ); +}; diff --git a/features/ics/apply-form/context/consts.ts b/features/ics/apply-form/context/consts.ts new file mode 100644 index 000000000..77f5b4c2e --- /dev/null +++ b/features/ics/apply-form/context/consts.ts @@ -0,0 +1 @@ +export const MAX_ADDITIONAL_ADDRESSES = 5; diff --git a/features/ics/apply-form/context/index.ts b/features/ics/apply-form/context/index.ts new file mode 100644 index 000000000..89ebd98ea --- /dev/null +++ b/features/ics/apply-form/context/index.ts @@ -0,0 +1,5 @@ +export * from './apply-data-provider'; +export * from './apply-form-provider'; +export * from './consts'; +export * from './types'; +export * from './use-verify-message'; diff --git a/features/ics/apply-form/context/types.ts b/features/ics/apply-form/context/types.ts new file mode 100644 index 000000000..16d067554 --- /dev/null +++ b/features/ics/apply-form/context/types.ts @@ -0,0 +1,17 @@ +import { Address } from 'viem'; + +export type AdditionalAddress = { + address: string; + signature: string; + verified?: boolean; +}; + +export type ApplyFormInputType = { + additionalAddresses: AdditionalAddress[]; + twitterLink?: string; + discordLink?: string; +}; + +export type ApplyFormNetworkData = { + mainAddress: Address; +}; diff --git a/features/ics/apply-form/context/use-apply-flow.ts b/features/ics/apply-form/context/use-apply-flow.ts new file mode 100644 index 000000000..736df1305 --- /dev/null +++ b/features/ics/apply-form/context/use-apply-flow.ts @@ -0,0 +1,71 @@ +import { IcsApplyDto, IcsResponseDto, useIcsState } from 'features/ics/shared'; +import { endpoints, useSurveysMutation } from 'modules/surveys-sdk'; +import { useCallback } from 'react'; +import type { + Executable, + FlowResolver, +} from 'shared/hook-form/form-controller'; +import type { ApplyFormInputType, ApplyFormNetworkData } from './types'; +import { useModalStages } from './use-modal-stages'; + +export type ApplyFlow = { action: 'submit' } & Executable; + +const transformFormDataToApiPayload = ( + form: ApplyFormInputType, + data: ApplyFormNetworkData, +): IcsApplyDto => ({ + mainAddress: data.mainAddress, + additionalAddresses: form.additionalAddresses, + twitterLink: form.twitterLink || undefined, + discordLink: form.discordLink || undefined, +}); + +export const useApplyFlowResolver = (): FlowResolver< + ApplyFormInputType, + ApplyFormNetworkData, + ApplyFlow +> => { + const stages = useModalStages(); + const { reset } = useIcsState(); + const mutation = useSurveysMutation( + endpoints.icsApply, + { mutationKey: ['ics-apply'] }, + ); + + return useCallback( + (input, data) => ({ + action: 'submit' as const, + submit: async () => { + const apiPayload = transformFormDataToApiPayload(input, data); + + try { + stages.pending(); + await mutation.mutateAsync(apiPayload); + window.scrollTo({ top: 0 }); + reset(false); + stages.success(); + } catch (error: any) { + let errorMessage = 'Something went wrong'; + let errorDetails: string[] = []; + + if (error?.response?.data?.message) { + const messages = error.response.data.message; + if (Array.isArray(messages)) { + errorDetails = messages; + errorMessage = `Validation failed: ${messages.length} error${messages.length > 1 ? 's' : ''}`; + } else if (typeof messages === 'string') { + errorMessage = messages; + } + } else if (error?.message) { + errorMessage = error.message; + } + + window.scrollTo({ top: 0 }); + stages.failed({ message: errorMessage, details: errorDetails }); + throw error; + } + }, + }), + [mutation, reset, stages], + ); +}; diff --git a/features/ics/apply-form/context/use-apply-form-validation.ts b/features/ics/apply-form/context/use-apply-form-validation.ts new file mode 100644 index 000000000..722799913 --- /dev/null +++ b/features/ics/apply-form/context/use-apply-form-validation.ts @@ -0,0 +1,117 @@ +import { + useFormValidation, + ValidationError, +} from 'shared/hook-form/validation'; +import { isAddress, isAddressEqual, isHex } from 'viem'; +import { useApplyFormData } from './apply-data-provider'; +import { MAX_ADDITIONAL_ADDRESSES } from './consts'; +import { ApplyFormNetworkData, type ApplyFormInputType } from './types'; +import { useRawVefiryMessage } from './use-verify-message'; + +const twitterUrlRegex = /^https:\/\/(twitter\.com|x\.com)\/\w+\/status\/\d+$/; +const discordMessageRegex = /^https:\/\/discord\.com\/channels\/\d+\/\d+\/\d+$/; + +export const useApplyFormValidation = () => { + const { mainAddress } = useApplyFormData(true); + const verifyMessage = useRawVefiryMessage(mainAddress); + + return useFormValidation( + 'additionalAddresses', + async ( + { additionalAddresses, twitterLink, discordLink }, + { mainAddress }, + validate, + ) => { + await validate('additionalAddresses', () => { + if (additionalAddresses.length > MAX_ADDITIONAL_ADDRESSES) { + throw new ValidationError( + 'additionalAddresses.4.address', + 'Maximum 5 additional addresses allowed', + ); + } + }); + + for (const [ + index, + { address, signature, verified }, + ] of additionalAddresses.entries()) { + const addressPath = `additionalAddresses.${index}.address` as any; + const signaturePath = `additionalAddresses.${index}.signature` as any; + + await validate(addressPath, () => { + if (!address || !isAddress(address)) { + throw new ValidationError(addressPath, ''); + } + + if (isAddressEqual(address, mainAddress)) { + throw new ValidationError( + addressPath, + 'Additional address cannot be the same as main address', + ); + } + + const hasDuplicateAddresses = additionalAddresses.some( + (a, i) => + i !== index && + isAddress(a.address) && + isAddressEqual(address, a.address), + ); + + if (hasDuplicateAddresses) { + throw new ValidationError( + addressPath, + 'Duplicate addresses are not allowed', + ); + } + }); + + await validate(signaturePath, async () => { + if (!signature || !isHex(signature)) { + throw new ValidationError(signaturePath, ''); + } + + if (verified) return; + + try { + if (!isAddress(address)) { + throw new ValidationError(addressPath, ''); + } + + const isValid = await verifyMessage({ address, signature }); + + if (!isValid) { + throw new ValidationError( + signaturePath, + 'Invalid signature for this address and message', + ); + } + } catch { + throw new ValidationError( + signaturePath, + 'Invalid signature for this address and message', + ); + } + }); + } + + await validate('twitterLink', () => { + if (twitterLink && !twitterUrlRegex.test(twitterLink)) { + throw new ValidationError( + 'twitterLink', + 'Must be a valid Twitter/X status URL', + ); + } + }); + + await validate('discordLink', () => { + if (discordLink && !discordMessageRegex.test(discordLink)) { + throw new ValidationError( + 'discordLink', + 'Must be a valid Discord message URL', + ); + } + }); + }, + [verifyMessage], + ); +}; diff --git a/features/ics/apply-form/context/use-modal-stages.tsx b/features/ics/apply-form/context/use-modal-stages.tsx new file mode 100644 index 000000000..d0c9d3e9e --- /dev/null +++ b/features/ics/apply-form/context/use-modal-stages.tsx @@ -0,0 +1,64 @@ +import { useMemo } from 'react'; +import { + TxStageFail, + TxStagePending, + TxStageSuccess, + useTransitStage, +} from 'shared/transaction-modal'; +import { extractErrorMessage, getErrorCode } from 'utils'; + +export const useModalStages = () => { + const transitStage = useTransitStage(); + + return useMemo( + () => ({ + pending: () => + transitStage( + , + ), + + success: () => + transitStage( + , + ), + + failed: (error: unknown) => { + let errorContent; + + if (typeof error === 'object' && error !== null && 'details' in error) { + const errorObj = error as { message: string; details: string[] }; + errorContent = ( + <> + {errorObj.message} +
          + {errorObj.details.length > 0 && ( +
            + {errorObj.details.map((detail, index) => ( +
          • {detail}
          • + ))} +
          + )} + + ); + } else { + errorContent = extractErrorMessage(error); + } + + return transitStage( + , + ); + }, + }), + [transitStage], + ); +}; diff --git a/features/ics/apply-form/context/use-verify-message.ts b/features/ics/apply-form/context/use-verify-message.ts new file mode 100644 index 000000000..cffded274 --- /dev/null +++ b/features/ics/apply-form/context/use-verify-message.ts @@ -0,0 +1,61 @@ +import { useMainnetOnlyWagmi } from 'modules/web3/web3-provider/web3-provider'; +import { useCallback } from 'react'; +import { Address, Hex, isAddress, PublicClient } from 'viem'; +import { generateAddressMessage, generateSocialMessage } from './utils'; +import { usePublicClient } from 'wagmi'; +import { useApplyFormData } from './apply-data-provider'; + +type VerifyMessageProps = { + address: Address; + signature: Hex; +}; + +export const useAddressMessage = (address?: string) => { + const { mainAddress } = useApplyFormData(true); + + return address && isAddress(address) + ? generateAddressMessage(address, mainAddress) + : ''; +}; + +export const useSocialMessages = () => { + const { mainAddress } = useApplyFormData(true); + const twitterMessage = generateSocialMessage(mainAddress, 'twitter'); + const discordMessage = generateSocialMessage(mainAddress, 'discord'); + + return { + twitterMessage, + discordMessage, + }; +}; + +export const useRawVefiryMessage = (mainAddress: Address) => { + const { publicClientMainnet } = useMainnetOnlyWagmi(); + const publicClient = usePublicClient(); + + return useCallback( + async ({ address, signature }: VerifyMessageProps) => { + const message = generateAddressMessage(address, mainAddress); + const clients = [publicClient] as PublicClient[]; + if (publicClientMainnet.chain?.id !== publicClient?.chain.id) { + clients.push(publicClientMainnet); + } + + const isValid = ( + await Promise.all( + clients.map((client) => + client?.verifyMessage({ address, message, signature }), + ), + ) + ).some(Boolean); + + return isValid; + }, + [mainAddress, publicClient, publicClientMainnet], + ); +}; + +export const useVerifyMessage = () => { + const { mainAddress } = useApplyFormData(true); + return useRawVefiryMessage(mainAddress); +}; diff --git a/features/ics/apply-form/context/utils.ts b/features/ics/apply-form/context/utils.ts new file mode 100644 index 000000000..74ead0a94 --- /dev/null +++ b/features/ics/apply-form/context/utils.ts @@ -0,0 +1,14 @@ +import { Address } from 'viem'; + +export const generateSocialMessage = ( + address: Address, + platform: 'twitter' | 'discord', +) => { + return `This post is proof that I am the owner of this ${platform === 'twitter' ? 'X' : 'Discord'} account. My address to get verified for ICS: ${address.toLowerCase()}`; +}; + +export const generateAddressMessage = ( + address: Address, + mainAddress: Address, +) => + `Verify ownership of address ${address.toLowerCase()} for ICS with main address ${mainAddress.toLowerCase()}`; diff --git a/features/ics/apply-form/controls/additional-addresses.tsx b/features/ics/apply-form/controls/additional-addresses.tsx new file mode 100644 index 000000000..a0ca5864c --- /dev/null +++ b/features/ics/apply-form/controls/additional-addresses.tsx @@ -0,0 +1,70 @@ +import { ButtonIcon, Plus, Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { FC, useCallback } from 'react'; +import { useFieldArray, useFormContext } from 'react-hook-form'; +import { Chip, FormTitle, MatomoLink, Stack } from 'shared/components'; +import { MAX_ADDITIONAL_ADDRESSES, type ApplyFormInputType } from '../context'; +import { AddressItem } from './address-item'; + +export const AdditionalAddresses: FC = () => { + const { control } = useFormContext(); + const { fields, append, remove } = useFieldArray({ + control, + name: 'additionalAddresses', + }); + + const handleAddAddress = useCallback(() => { + if (fields.length < MAX_ADDITIONAL_ADDRESSES) { + append({ address: '', signature: '' }); + } + }, [append, fields.length]); + + const handleRemoveAddress = useCallback( + (index: number) => { + remove(index); + }, + [remove], + ); + + return ( + + + Optional}>Additional Addresses + + You can add up to {MAX_ADDITIONAL_ADDRESSES} addresses where your + achievements are stored. To prove you own each address, sign a message + on Etherscan. For more info see{' '} + + the guide + + + + + {fields.map((field, index) => ( + + ))} + + {fields.length < MAX_ADDITIONAL_ADDRESSES && ( + } + variant="translucent" + size="sm" + onClick={handleAddAddress} + fullwidth + data-testid="addNewAddressBtn" + > + Add new address + + )} + + ); +}; diff --git a/features/ics/apply-form/controls/address-item.tsx b/features/ics/apply-form/controls/address-item.tsx new file mode 100644 index 000000000..21d36316b --- /dev/null +++ b/features/ics/apply-form/controls/address-item.tsx @@ -0,0 +1,223 @@ +import { + Button, + ButtonIcon, + External, + Input, + Text, +} from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { CategoryItemsWrapper } from 'features/ics/score-system/styles'; +import { FC, useCallback, useState } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { CopyButton, MatomoLink, Stack } from 'shared/components'; +import { VerifiedChip } from 'shared/components/input-address/verified-chip'; +import { + AddressInputHookForm, + TextInputHookForm, +} from 'shared/hook-form/controls'; +import { isAddress, isHex } from 'viem'; +import { + useAddressMessage, + useVerifyMessage, + type ApplyFormInputType, +} from '../context'; + +export type AddressItemProps = { + field: { id: string; address: string; signature: string; verified?: boolean }; + index: number; + onRemove: (index: number) => void; +}; + +export const AddressItem: FC = ({ + field, + index, + onRemove, +}) => { + const watchedAddress = useWatch({ + name: `additionalAddresses.${index}.address` as const, + }) as string; + + const verified = useWatch({ + name: `additionalAddresses.${index}.verified` as const, + }); + + const { getValues, setError, clearErrors, setValue } = + useFormContext(); + + const message = useAddressMessage(watchedAddress); + + const [isVerifying, setIsVerifying] = useState(false); + + const verifyMessage = useVerifyMessage(); + + const onVerify = useCallback( + async (index: number) => { + if (isVerifying || verified) return; + + const currentAddresses = getValues('additionalAddresses'); + const { address, signature } = currentAddresses[index]; + + if (!isHex(signature)) { + setError(`additionalAddresses.${index}.signature`, { + type: 'manual', + message: 'Invalid signature format', + }); + return; + } + + if (!isAddress(address)) { + setError(`additionalAddresses.${index}.address`, { + type: 'manual', + message: 'Invalid Ethereum address', + }); + return; + } + + setIsVerifying(true); + + try { + const isValid = await verifyMessage({ address, signature }); + + if (isValid) { + clearErrors(`additionalAddresses.${index}.signature`); + setValue(`additionalAddresses.${index}.verified`, true); + } else { + setError(`additionalAddresses.${index}.signature`, { + type: 'manual', + message: 'Invalid signature for this address and message', + }); + } + } catch (error) { + setError(`additionalAddresses.${index}.signature`, { + type: 'manual', + message: 'Invalid signature format or verification failed', + }); + } finally { + setIsVerifying(false); + } + }, + [ + clearErrors, + getValues, + setError, + verifyMessage, + isVerifying, + verified, + setValue, + ], + ); + + return ( + + + + Additional address #{index + 1} + + + + {verified ? ( + + + Additional address #{index + 1}{' '} + Verified + + } + /> + + ) : ( + + + Step 1. Insert your Ethereum address + + + + + Step 2. Copy the message and sign it on Etherscan (or other tool) + + + + + } + size="xs" + variant="translucent" + > + Sign + + + + } + /> + + + + Step 3. Paste the signature in the field below + + void onVerify(index)} + disabled={isVerifying} + data-testid="verifySignatureBtn" + > + {isVerifying ? 'Verifying...' : 'Verify'} + + } + /> + + + )} + + ); +}; diff --git a/features/ics/apply-form/controls/index.ts b/features/ics/apply-form/controls/index.ts new file mode 100644 index 000000000..bd06176e3 --- /dev/null +++ b/features/ics/apply-form/controls/index.ts @@ -0,0 +1,4 @@ +export * from './additional-addresses'; +export * from './main-address'; +export * from './social-proof'; +export * from './submit-button'; diff --git a/features/ics/apply-form/controls/main-address.tsx b/features/ics/apply-form/controls/main-address.tsx new file mode 100644 index 000000000..be9ad0252 --- /dev/null +++ b/features/ics/apply-form/controls/main-address.tsx @@ -0,0 +1,31 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { FormTitle, InputAddress, Stack } from 'shared/components'; +import { VerifiedChip } from 'shared/components/input-address/verified-chip'; +import { useApplyFormData } from '../context'; + +export const MainAddress: FC = () => { + const { mainAddress } = useApplyFormData(true); + + return ( + + + Main address + + You are requesting ICS operator type to the following address: + + + + Main address Verified + + } + value={mainAddress} + /> + + ); +}; diff --git a/features/ics/apply-form/controls/social-proof.tsx b/features/ics/apply-form/controls/social-proof.tsx new file mode 100644 index 000000000..ac07bdb48 --- /dev/null +++ b/features/ics/apply-form/controls/social-proof.tsx @@ -0,0 +1,122 @@ +import { Input, Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { CategoryItemsWrapper } from 'features/ics/score-system/styles'; +import { FC } from 'react'; +import { + Chip, + CopyButton, + FormTitle, + IconTooltip, + MatomoLink, + Stack, +} from 'shared/components'; +import { TextInputHookForm } from 'shared/hook-form/controls'; +import { useSocialMessages } from '../context'; + +export const SocialProof: FC = () => { + const { twitterMessage, discordMessage } = useSocialMessages(); + + return ( + + + Optional}>Socials + + You can add your social accounts. To prove you own an account, post a + message. For more info see{' '} + + the guide + + . + + + + {/* Twitter Section */} + + + X (formerly Twitter) + + + + + + Step 1. Prove the ownership of the X account by posting a tweet + with the following text. + + + e.target.select()} + onClick={(e) => (e.target as HTMLInputElement).select()} + value={twitterMessage} + fullwidth + rightDecorator={} + /> + + + + Step 2. Paste the link to this post. + + + + + + + {/* Discord Section */} + + + Discord + + + + + + Step 1. Prove the ownership of the Discord account by posting the + following message to{' '} + + the CSM channel + + .{' '} + + + + e.target.select()} + onClick={(e) => (e.target as HTMLInputElement).select()} + value={discordMessage} + fullwidth + rightDecorator={} + /> + + + + Step 2. Paste the link to this message. + + + + + + + ); +}; diff --git a/features/ics/apply-form/controls/submit-button.tsx b/features/ics/apply-form/controls/submit-button.tsx new file mode 100644 index 000000000..5ad0a0dcd --- /dev/null +++ b/features/ics/apply-form/controls/submit-button.tsx @@ -0,0 +1,8 @@ +import { FC } from 'react'; +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; + +export const SubmitButton: FC = () => ( + + Submit application + +); diff --git a/features/ics/apply-form/index.ts b/features/ics/apply-form/index.ts new file mode 100644 index 000000000..fd8b28662 --- /dev/null +++ b/features/ics/apply-form/index.ts @@ -0,0 +1,2 @@ +export { ApplyForm } from './apply-form'; +export { ApplyFormProvider } from './context'; diff --git a/features/ics/form-status/components/application-tip.tsx b/features/ics/form-status/components/application-tip.tsx new file mode 100644 index 000000000..48b85afba --- /dev/null +++ b/features/ics/form-status/components/application-tip.tsx @@ -0,0 +1,27 @@ +import { Text } from '@lidofinance/lido-ui'; +import { IcsResponseDto } from 'features/ics/shared'; +import { FC } from 'react'; +import { BlockStyled } from '../styles'; +import { Stack } from 'shared/components'; + +type Props = Pick; + +export const ApplicationTip: FC = ({ comments }) => { + const show = !!comments.additionalAddresses?.filter((c) => !!c).length; + + if (!show) return null; + return ( + + + + What you can do + + + If you believe that these address(es) were incorrectly flagged, you + may submit an appeal on the Lido Research Forum for review by the CSM + Committee + + + + ); +}; diff --git a/features/ics/form-status/components/application.tsx b/features/ics/form-status/components/application.tsx new file mode 100644 index 000000000..41e113414 --- /dev/null +++ b/features/ics/form-status/components/application.tsx @@ -0,0 +1,117 @@ +import { Input, Text } from '@lidofinance/lido-ui'; +import { parseISO } from 'date-fns'; +import { IcsResponseDto } from 'features/ics/shared'; +import { FC } from 'react'; +import { InputAddress, Stack } from 'shared/components'; +import { formatDate } from 'utils'; +import { AccordionStyle } from '../styles'; + +type CommentsSectionProps = Pick< + IcsResponseDto, + 'comments' | 'form' | 'createdAt' +>; + +export const Application: FC = ({ + comments, + form, + createdAt, +}) => ( + + + Your application + + + Submitted {formatDate(parseISO(createdAt), 'dd.MM.yyyy')} + + + } + > + + + + Main Address + + + + + {comments.mainAddress} + + + + {form.additionalAddresses?.length ? ( + + + Additional addresses + + {form.additionalAddresses?.map((address, index) => ( + + + + {comments.additionalAddresses?.[index]} + + + ))} + + ) : null} + {form.twitterLink || form.discordLink ? ( + + + Socials + + {form.twitterLink && ( + + + + {comments.twitterLink} + + + )} + {form.discordLink && ( + + + + {comments.discordLink} + + + )} + + ) : null} + + +); diff --git a/features/ics/form-status/components/index.ts b/features/ics/form-status/components/index.ts new file mode 100644 index 000000000..b0300ad14 --- /dev/null +++ b/features/ics/form-status/components/index.ts @@ -0,0 +1,6 @@ +export * from './application-tip'; +export * from './application'; +export * from './score-category'; +export * from './score-item'; +export * from './score-points'; +export * from './status-header'; diff --git a/features/ics/form-status/components/score-category.tsx b/features/ics/form-status/components/score-category.tsx new file mode 100644 index 000000000..d998c71fc --- /dev/null +++ b/features/ics/form-status/components/score-category.tsx @@ -0,0 +1,61 @@ +import { Text } from '@lidofinance/lido-ui'; +import { Points } from 'features/ics/score-system/points'; +import { + CategoryItemsWrapper, + ScoreAccordionstyle, +} from 'features/ics/score-system/styles'; +import { TipWrapper } from 'features/monitoring/attestation-rate-section/styles'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { IcsFormStatus, IcsScoresDto, ScoreSource } from 'features/ics/shared'; +import { FailIcon, SuccessIcon } from '../styles'; +import { calculateScores } from '../utils'; +import { ScoreItem } from './score-item'; + +type ScoreCategoryProps = { + category: ScoreSource; + scores: IcsScoresDto; + status: IcsFormStatus; +}; + +export const ScoreCategory: FC = ({ + category, + scores, + status, +}) => { + const value = calculateScores(scores, category.id); + const isEnougth = value >= category.min; + const showIcons = status !== 'APPROVED'; + + const categoryHeader = ( + + + {showIcons && (isEnougth ? : )}{' '} + {category.title} + + + + + + + + ); + + return ( + + + {!isEnougth && ( + + You did not reach the minimum score of{' '} + required for this category + + )} + + {category.items.map((item) => ( + + ))} + + + + ); +}; diff --git a/features/ics/form-status/components/score-chip/index.ts b/features/ics/form-status/components/score-chip/index.ts new file mode 100644 index 000000000..11e29b456 --- /dev/null +++ b/features/ics/form-status/components/score-chip/index.ts @@ -0,0 +1 @@ +export * from './score-chip'; diff --git a/features/ics/form-status/components/score-chip/score-chip.tsx b/features/ics/form-status/components/score-chip/score-chip.tsx new file mode 100644 index 000000000..b2eae64dc --- /dev/null +++ b/features/ics/form-status/components/score-chip/score-chip.tsx @@ -0,0 +1,25 @@ +import { FC, PropsWithChildren, ReactNode } from 'react'; +import { ChipStyle, Variants } from './style'; +import { Check, Close } from '@lidofinance/lido-ui'; +import { ReactComponent as Clock } from 'assets/icons/clock.svg'; + +type Props = { + type?: Variants; +}; + +const ICONS: Record = { + default: , + success: , + error: , + pending: , +}; + +export const ScoreChip: FC> = ({ + children, + type = 'default', +}) => ( + + {ICONS[type]} + {children} + +); diff --git a/features/ics/form-status/components/score-chip/style.ts b/features/ics/form-status/components/score-chip/style.ts new file mode 100644 index 000000000..44204386c --- /dev/null +++ b/features/ics/form-status/components/score-chip/style.ts @@ -0,0 +1,37 @@ +import styled, { css } from 'styled-components'; + +export type Variants = keyof typeof variants; + +const variants = { + default: css` + color: var(--lido-color-text); + `, + success: css` + color: var(--lido-color-success); + `, + error: css` + color: var(--lido-color-error); + `, + pending: css` + color: var(--lido-color-textSecondary); + `, +}; + +export const ChipStyle = styled.div<{ $variant?: Variants }>` + display: flex; + flex-direction: row; + gap: ${({ theme }) => theme.spaceMap.xs}px; + + width: fit-content; + padding: 2px 12px; + align-items: center; + white-space: nowrap; + + border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px; + background: color-mix(in srgb, currentColor 15%, transparent); + + font-size: ${({ theme }) => theme.fontSizesMap.xs}px; + line-height: ${({ theme }) => theme.fontSizesMap.xl}px; + font-weight: 700; + ${(props) => variants[props.$variant || 'default']} +`; diff --git a/features/ics/form-status/components/score-item.tsx b/features/ics/form-status/components/score-item.tsx new file mode 100644 index 000000000..e54fe5b8d --- /dev/null +++ b/features/ics/form-status/components/score-item.tsx @@ -0,0 +1,27 @@ +import { Text } from '@lidofinance/lido-ui'; +import { Points } from 'features/ics/score-system/points'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { ScoreItem as ScoreItemType } from 'features/ics/shared'; + +type ScoreItemProps = { + item: ScoreItemType; + value: number; +}; + +export const ScoreItem: FC = ({ item, value }) => { + return ( + + + {item.icon} + + {item.name} + + + + + + + + ); +}; diff --git a/features/ics/form-status/components/score-points.tsx b/features/ics/form-status/components/score-points.tsx new file mode 100644 index 000000000..a2f06bb6c --- /dev/null +++ b/features/ics/form-status/components/score-points.tsx @@ -0,0 +1,51 @@ +import { Text } from '@lidofinance/lido-ui'; +import { Points } from 'features/ics/score-system/points'; +import { + IcsResponseDto, + SCORE_SOURCES, + TOTAL_SCORE_REQUIRED, +} from 'features/ics/shared'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { calculateScores, isMinScoresReached } from '../utils'; +import { ScoreCategory } from './score-category'; +import { FailIcon, SemiFailIcon, SuccessIcon } from '../styles'; + +type ScoreCategoryProps = Pick; + +export const ScorePoints: FC = ({ scores, status }) => { + const isMinReached = isMinScoresReached(scores); + const total = calculateScores(scores); + const isEnougth = total >= TOTAL_SCORE_REQUIRED; + const showIcons = status !== 'APPROVED'; + return ( + + + + {showIcons && + (isEnougth ? ( + isMinReached ? ( + + ) : ( + + ) + ) : ( + + ))}{' '} + Total Score Breakdown + + + + + + {SCORE_SOURCES.map((category) => ( + + ))} + + ); +}; diff --git a/features/ics/form-status/components/status-header.tsx b/features/ics/form-status/components/status-header.tsx new file mode 100644 index 000000000..9a4efe9e1 --- /dev/null +++ b/features/ics/form-status/components/status-header.tsx @@ -0,0 +1,223 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts'; +import { + ICS_ROUND, + IcsCommentsDto, + IcsFormStatus, + IcsScoresDto, + TOTAL_SCORE_REQUIRED, + TypeStatus, +} from 'features/ics/shared'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { getOperatorTypeQuery } from 'shared/hooks'; +import { LocalLink } from 'shared/navigate'; + +import { NodeOperatorId, OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { + NodeOperatorOwner, + useDappStatus, + useNodeOperatorId, + useOperatorOwner, +} from 'modules/web3'; +import { isAddressEqual } from 'viem'; +import { calculateScores, isMinScoresReached } from '../utils'; +import { ScoreChip } from './score-chip'; + +type StatusHeaderProps = { + typeStatus: TypeStatus; + status?: IcsFormStatus; + comments?: IcsCommentsDto; + scores?: IcsScoresDto; +}; + +const getStatus = ( + status: IcsFormStatus | undefined, + typeStatus: TypeStatus, +) => { + switch (status) { + case 'APPROVED': + return ( + + Approved + + ); + case 'REJECTED': + return Rejected; + case 'REVIEW': + return Pending; + default: + return null; + } +}; + +const getProofStatus = (typeStatus: TypeStatus) => { + switch (typeStatus) { + case 'CLAIMED': + return Claimed; + case 'ISSUED': + return Issued; + case 'OWNER_ISSUED': + return Approved; + default: + return Pending; + } +}; + +const useHint = ( + status: IcsFormStatus | undefined, + typeStatus: TypeStatus, + comments: IcsCommentsDto | undefined, + scores: IcsScoresDto | undefined, + owner: NodeOperatorOwner | undefined, + nodeOperatorId: NodeOperatorId | undefined, +) => { + switch (true) { + case typeStatus === 'CLAIMED': + return You successfully claimed your Operator type; + case typeStatus === 'ISSUED' && !!owner: + return ( + <> + You're already eligible to claim ICS type + + To claim your current address should be set as your Node Operator + owner + + + ); + case typeStatus === 'ISSUED' && nodeOperatorId === undefined: + return ( + <> + + Create a new Node Operator with ICS operator type + + +
          + + + +
          + + ); + case typeStatus === 'ISSUED': + return ( + <> + + Claim your new operator type on the “Claim operator type” tab + + +
          + + + +
          + + ); + case typeStatus === 'OWNER_ISSUED': + return ( + <> + + Node Operator's owner address is already eligible to claim ICS + type + + + Connect with your Node Operator's owner address to claim ICS + type + + + ); + case status === 'REJECTED': + if (comments?.reason) { + return {comments?.reason}; + } + if (scores) { + const isMinReached = isMinScoresReached(scores); + const totalScore = calculateScores(scores); + + // Check if total score is sufficient but minimum category requirements are not met + if (totalScore >= TOTAL_SCORE_REQUIRED && !isMinReached) { + return ( + + Your application did not reach the minimum score required for some + categories + + ); + } + + return ( + + Your application earned {totalScore} out of the{' '} + {TOTAL_SCORE_REQUIRED} points required to qualify + + ); + } + return null; + case status === 'REVIEW': + return ( + + The application will be evaluated in {ICS_ROUND.assessedDate}. You + cannot change the application while it is being reviewed. + + ); + case status === 'APPROVED': + return ( + + Please await issuance; this process typically takes up to three weeks + + ); + default: + return null; + } +}; + +export const StatusHeader: FC = ({ + status, + typeStatus, + comments, + scores, +}) => { + const { address } = useDappStatus(); + const nodeOperatorId = useNodeOperatorId(); + const { data: owner } = useOperatorOwner(nodeOperatorId); + + const otherOwner = + owner && address && !isAddressEqual(owner.address, address) + ? owner + : undefined; + + const statusChip = getStatus(status, typeStatus); + const proofChip = getProofStatus(typeStatus); + const hint = useHint( + status, + typeStatus, + comments, + scores, + otherOwner, + nodeOperatorId, + ); + + return ( + + {status && ( + + + Application + + {statusChip} + + )} + {(!status || status === 'APPROVED') && ( + + + Operator type + + {proofChip} + + )} + {hint} + + ); +}; diff --git a/features/ics/form-status/form-status.tsx b/features/ics/form-status/form-status.tsx new file mode 100644 index 000000000..24b22188c --- /dev/null +++ b/features/ics/form-status/form-status.tsx @@ -0,0 +1,54 @@ +import { Block, Button, Divider } from '@lidofinance/lido-ui'; +import { FC, useCallback } from 'react'; +import { Stack } from 'shared/components'; +import { TypeStatus } from '../shared'; +import { IcsResponseDto } from '../shared/types'; +import { + Application, + ApplicationTip, + ScorePoints, + StatusHeader, +} from './components'; + +type FormStatusProps = { + data: IcsResponseDto; + typeStatus: TypeStatus; + reset: () => void; +}; + +export const FormStatus: FC = ({ + data, + typeStatus, + reset, +}) => { + const { status, form, comments, createdAt, scores } = data; + + const handle = useCallback(() => { + window.scrollTo({ top: 0 }); + reset(); + }, [reset]); + + const haveScores = Object.values(scores).some((score) => score !== null); + + return ( + + + + {(status !== 'REVIEW' || haveScores) && } + {haveScores && } + {status === 'REJECTED' && } + + {status === 'REJECTED' && ( + + )} + + + ); +}; diff --git a/features/ics/form-status/index.ts b/features/ics/form-status/index.ts new file mode 100644 index 000000000..3152b8355 --- /dev/null +++ b/features/ics/form-status/index.ts @@ -0,0 +1 @@ +export { FormStatus } from './form-status'; diff --git a/features/ics/form-status/proof-status.tsx b/features/ics/form-status/proof-status.tsx new file mode 100644 index 000000000..722f5894a --- /dev/null +++ b/features/ics/form-status/proof-status.tsx @@ -0,0 +1,16 @@ +import { Block } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { TypeStatus } from '../shared'; +import { StatusHeader } from './components'; + +type FormStatusProps = { + typeStatus: TypeStatus; +}; + +export const ProofStatus: FC = ({ typeStatus }) => { + return ( + + + + ); +}; diff --git a/features/ics/form-status/styles.ts b/features/ics/form-status/styles.ts new file mode 100644 index 000000000..c02c5c4ed --- /dev/null +++ b/features/ics/form-status/styles.ts @@ -0,0 +1,92 @@ +import styled, { css } from 'styled-components'; +import { Accordion, Block, Check, Close } from '@lidofinance/lido-ui'; + +export const FormStatusStyled = styled(Block)` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spaceMap.lg}px; + padding: ${({ theme }) => theme.spaceMap.lg}px; + border-radius: ${({ theme }) => theme.borderRadiusesMap.md}px; + border: 1px solid var(--lido-color-border); + background: var(--lido-color-background); +`; + +export const StatusHeaderStyled = styled.div` + padding: ${({ theme }) => theme.spaceMap.md}px 0; + border-bottom: 1px solid var(--lido-color-border); +`; + +export const ScoreRowStyled = styled.div` + padding: ${({ theme }) => theme.spaceMap.sm}px; + border-radius: ${({ theme }) => theme.borderRadiusesMap.sm}px; + border: 1px solid var(--lido-color-border); + background: var(--lido-color-foreground); + + & > div { + flex: 1; + } + + & > div:first-child > div:nth-child(2) { + flex: 1; + } +`; + +export const ScoreValueStyled = styled.div<{ $passed: boolean }>` + font-size: ${({ theme }) => theme.fontSizesMap.sm}px; + font-weight: 700; + + ${({ $passed }) => + $passed + ? css` + color: var(--lido-color-success); + ` + : css` + color: var(--lido-color-error); + `} +`; + +export const RequiredScoreStyled = styled.div<{ $passed: boolean }>` + font-size: ${({ theme }) => theme.fontSizesMap.xs}px; + color: ${({ $passed }) => + $passed ? 'var(--lido-color-success)' : 'var(--lido-color-error)'}; +`; + +export const AccordionStyle = styled(Accordion)` + margin: 0; + + background: var(--lido-color-backgroundSecondary); + /* padding: 20px; */ + + & > div:first-child { + padding: 20px; + } + + & > div + div > div { + padding: 0 20px 20px 20px; + } + + p, + ul, + ol { + margin: 0; + } +`; + +export const BlockStyled = styled(Block)` + background: var(--lido-color-backgroundSecondary); +`; + +export const FailIcon = styled(Close)` + color: var(--lido-color-error); + vertical-align: middle; +`; + +export const SemiFailIcon = styled(Close)` + color: var(--lido-color-warning); + vertical-align: middle; +`; + +export const SuccessIcon = styled(Check)` + color: var(--lido-color-success); + vertical-align: middle; +`; diff --git a/features/ics/form-status/utils.ts b/features/ics/form-status/utils.ts new file mode 100644 index 000000000..dce0c602f --- /dev/null +++ b/features/ics/form-status/utils.ts @@ -0,0 +1,35 @@ +import { fromPairs } from 'lodash'; +import { SCORE_SOURCES } from '../shared/score-data'; +import { IcsScoresDto } from '../shared/types'; + +const summ = (acc: number, item?: number) => acc + (item ?? 0); + +const getScoreCategurySum = (scores: IcsScoresDto) => { + return fromPairs( + SCORE_SOURCES.map(({ id, max, items }) => { + const points = items.map(({ id }) => scores[id]).reduce(summ, 0); + const value = Math.min(points, max ?? points); + return [id, value] as const; + }), + ); +}; + +export const calculateScores = ( + scores: IcsScoresDto, + category?: string, +): number => { + const values = getScoreCategurySum(scores); + + if (!category) { + return Object.values(values).reduce(summ, 0); + } + + return values[category] ?? 0; +}; + +export const isMinScoresReached = (scores: IcsScoresDto) => { + const values = getScoreCategurySum(scores); + return SCORE_SOURCES.map(({ id, min }) => (values[id] ?? 0) >= min).every( + Boolean, + ); +}; diff --git a/features/ics/ics-apply-page.tsx b/features/ics/ics-apply-page.tsx new file mode 100644 index 000000000..db22886f3 --- /dev/null +++ b/features/ics/ics-apply-page.tsx @@ -0,0 +1,20 @@ +import { FC } from 'react'; + +import { FAQ_OPERATOR_TYPE } from 'faq'; +import { Faq, TypeBackButton } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { IcsPageSwitcher } from 'shared/navigate'; +import { IcsApply } from './ics-apply'; + +export const IcsApplyPage: FC = () => ( + } + > + + + + +); diff --git a/features/ics/ics-apply.tsx b/features/ics/ics-apply.tsx new file mode 100644 index 000000000..16bc77bfc --- /dev/null +++ b/features/ics/ics-apply.tsx @@ -0,0 +1,80 @@ +import { Block, Text } from '@lidofinance/lido-ui'; +import { useSiweAuth } from 'modules/siwe'; +import { useDappStatus } from 'modules/web3'; +import { FC } from 'react'; +import { NoSSRWrapper, Stack, WhenLoaded } from 'shared/components'; +import { Connect } from 'shared/wallet'; +import { ApplyForm } from './apply-form'; +import { FormStatus } from './form-status'; +import { ProofStatus } from './form-status/proof-status'; +import { IcsProviders, useIcsState } from './shared'; +import { SiweSignIn } from './siwe-sign-in'; + +const IcsApplyContent: FC = () => { + const { isAccountActive } = useDappStatus(); + const { token } = useSiweAuth(); + const { typeStatus, data, isPending, isTypePending, applyMode, reset } = + useIcsState(); + + if (!isAccountActive) { + return ( + + + + + Connect your wallet + + + Connect your wallet and sign a verification message to continue + + + + + + ); + } + + if (isTypePending) { + return ( + + + + ); + } + + if (typeStatus === 'CLAIMED') { + return ; + } + + if (!token) { + return ; + } + + if (isPending) { + return ( + + + + ); + } + + if (data && !applyMode) { + return ; + } + + if (!data && typeStatus !== 'PENDING') { + return ; + } + + return ; +}; + +export const IcsApply: FC = () => { + return ( + + + + + + ); +}; diff --git a/features/ics/ics-scores-page.tsx b/features/ics/ics-scores-page.tsx new file mode 100644 index 000000000..b6435642d --- /dev/null +++ b/features/ics/ics-scores-page.tsx @@ -0,0 +1,32 @@ +import { FC } from 'react'; + +import { FAQ_OPERATOR_TYPE } from 'faq'; +import { Faq, TypeBackButton } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { IcsPageSwitcher } from 'shared/navigate'; +import { IcsApplyButton } from './apply-button'; +import { RoundBanner } from './round-banner'; +import { ApplicationFlow, Introduction, ScoreSources } from './score-system'; +import { BlockStyle } from './score-system/styles'; +import { IcsProviders } from './shared'; + +export const IcsScoresPage: FC = () => ( + } + > + + + + + + + + + + + + +); diff --git a/features/ics/index.ts b/features/ics/index.ts new file mode 100644 index 000000000..4a3b40f25 --- /dev/null +++ b/features/ics/index.ts @@ -0,0 +1,3 @@ +export * from './ics-apply-page'; +export * from './ics-scores-page'; +export * from './form-status'; diff --git a/features/ics/round-banner/index.ts b/features/ics/round-banner/index.ts new file mode 100644 index 000000000..87d827628 --- /dev/null +++ b/features/ics/round-banner/index.ts @@ -0,0 +1 @@ +export * from './round-banner'; diff --git a/features/ics/round-banner/round-banner.tsx b/features/ics/round-banner/round-banner.tsx new file mode 100644 index 000000000..016939564 --- /dev/null +++ b/features/ics/round-banner/round-banner.tsx @@ -0,0 +1,26 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { StyledBlock } from './styles'; +import { Stack } from 'shared/components'; +import { ICS_ROUND } from '../shared/consts'; + +export const RoundBanner: FC = () => ( + + + + ICS Application Round #{ICS_ROUND.round} is ongoing + + + All applications received after {ICS_ROUND.startDate} will be evaluated + in {ICS_ROUND.assessedDate}. + {!ICS_ROUND.isPreciseAssessedDate && ( + <> + {' '} + Stay tuned for the announcement of the final date for Application + Round #{ICS_ROUND.round} + + )} + + + +); diff --git a/features/ics/round-banner/styles.tsx b/features/ics/round-banner/styles.tsx new file mode 100644 index 000000000..0c0813df0 --- /dev/null +++ b/features/ics/round-banner/styles.tsx @@ -0,0 +1,17 @@ +import { ThemeName } from '@lidofinance/lido-ui'; +import { HatBlock } from 'shared/components'; +import styled from 'styled-components'; + +export const StyledBlock = styled(HatBlock)` + --first-color: ${({ theme }) => + theme.name === ThemeName.light ? `#bfdbfe` : `#55657b`}; + --second-color: ${({ theme }) => + theme.name === ThemeName.light ? `#ccfbf1` : `#59837a`}; + + background: linear-gradient( + 106deg, + var(--first-color) 2.02%, + var(--second-color) 99.17% + ), + linear-gradient(108deg, #e2e4fc -0.19%, #dcfcf5 91.74%); +`; diff --git a/features/ics/score-system/application-flow.tsx b/features/ics/score-system/application-flow.tsx new file mode 100644 index 000000000..6d992312e --- /dev/null +++ b/features/ics/score-system/application-flow.tsx @@ -0,0 +1,58 @@ +import { Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES, PATH } from 'consts'; +import { FC, PropsWithChildren } from 'react'; +import { MatomoLink, Stack } from 'shared/components'; +import { LocalLink } from 'shared/navigate'; +import { Number, StepContent, StepWrapper } from './styles'; + +export const Step: FC> = ({ + number, + title, + children, +}) => { + return ( + + {number} + +

          {title}

          +

          {children}

          +
          +
          + ); +}; + +export const ApplicationFlow: FC = () => { + return ( + + + Application Flow + + + People interested in being included in{' '} + + the Identified Community Staker list + {' '} + must submit the application on the " + Application form" + sub-tab + + + After submission, the application undergoes semi-automated checks to + validate the provided information and assign the appropriate scores + + + If approved, the CSM Committee will initiate an Easy Track motion to + assign the operator type to the applicant’s address + + + Once the operator type is issued, it can be claimed via the CSM UI (for + existing operators), or it will be assigned automatically upon operator + creation (for new operators) + + + ); +}; diff --git a/features/ics/score-system/index.ts b/features/ics/score-system/index.ts new file mode 100644 index 000000000..3c98addc5 --- /dev/null +++ b/features/ics/score-system/index.ts @@ -0,0 +1,3 @@ +export * from './application-flow'; +export * from './introduction'; +export * from './score-sources'; diff --git a/features/ics/score-system/introduction.tsx b/features/ics/score-system/introduction.tsx new file mode 100644 index 000000000..3e98938fa --- /dev/null +++ b/features/ics/score-system/introduction.tsx @@ -0,0 +1,21 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; + +export const Introduction: FC = () => { + return ( + + + Introduction + + + The scoring system creates a clear path for independent stakers to + qualify as "Identified Community" operators. Your score + determines eligibility for the Identified Community Stakers List. Points + are awarded by submitting verifiable proofs; - across categories such as + experience, on-chain engagement, and community contributions - that + demonstrate your qualifications. + + + ); +}; diff --git a/features/ics/score-system/points.tsx b/features/ics/score-system/points.tsx new file mode 100644 index 000000000..412980bfa --- /dev/null +++ b/features/ics/score-system/points.tsx @@ -0,0 +1,10 @@ +import { FC } from 'react'; +import { Plural } from 'shared/components'; + +export const Points: FC<{ value: number | string }> = ({ value }) => { + return typeof value === 'number' ? ( + + ) : ( + <>{value} points + ); +}; diff --git a/features/ics/score-system/score-category.tsx b/features/ics/score-system/score-category.tsx new file mode 100644 index 000000000..22b25aa26 --- /dev/null +++ b/features/ics/score-system/score-category.tsx @@ -0,0 +1,45 @@ +import { Divider, Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { ScoreSource } from '../shared'; +import { Points } from './points'; +import { ScoreItem } from './score-item'; +import { ScoreAccordionstyle, CategoryItemsWrapper } from './styles'; + +type ScoreCategoryProps = { + category: ScoreSource; +}; + +export const ScoreCategory: FC = ({ category }) => { + const categoryHeader = ( + + + {category.title} + + + + Min: + + + + Max: + + + + ); + + return ( + + + + {category.description} + + + {category.items.map((item) => ( + + ))} + + + + ); +}; diff --git a/features/ics/score-system/score-item.tsx b/features/ics/score-system/score-item.tsx new file mode 100644 index 000000000..ab526f72f --- /dev/null +++ b/features/ics/score-system/score-item.tsx @@ -0,0 +1,34 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { ScoreItem as ScoreItemType } from '../shared'; +import { Points } from './points'; +import { ScoreAccordionstyle } from './styles'; + +type ScoreItemProps = { + item: ScoreItemType; +}; + +export const ScoreItem: FC = ({ item }) => { + return ( + + + {item.icon} + {item.name} + + + + + + + } + > + + {item.description} + + + ); +}; diff --git a/features/ics/score-system/score-sources.tsx b/features/ics/score-system/score-sources.tsx new file mode 100644 index 000000000..cf30c75f9 --- /dev/null +++ b/features/ics/score-system/score-sources.tsx @@ -0,0 +1,32 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { ScoreCategory } from './score-category'; +import { SCORE_SOURCES, TOTAL_SCORE_REQUIRED } from '../shared'; +import { Points } from './points'; + +export const ScoreSources: FC = () => { + return ( + + + Score sources + + + To be included in the list, applicants must obtain a sufficient score in + each category below as well as an overall score across all the + categories + + + + Total score required + + + + + + {SCORE_SOURCES.map((category) => ( + + ))} + + ); +}; diff --git a/features/ics/score-system/styles.ts b/features/ics/score-system/styles.ts new file mode 100644 index 000000000..102d9d424 --- /dev/null +++ b/features/ics/score-system/styles.ts @@ -0,0 +1,111 @@ +import { Block, Theme } from '@lidofinance/lido-ui'; +import { StackStyle } from 'shared/components'; +import { AccordionNavigatable } from 'shared/components/accordion-navigatable'; +import styled from 'styled-components'; + +export const BlockStyle = styled(Block)` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spaceMap.xxl}px; +`; + +export const Steps = styled.div` + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); + gap: ${({ theme }) => theme.spaceMap.xl}px; +`; + +export const Number = styled.div` + display: flex; + flex-direction: row; + flex-wrap: wrap; + width: 32px; + height: 32px; + justify-content: center; + align-items: center; + + border-radius: 100%; + border: 1px solid var(--lido-color-border); + + color: var(--lido-color-text); + font-size: 14px; + font-weight: 700; + line-height: 24px; + + margin-top: -4px; +`; + +export const StepWrapper = styled.div` + display: flex; + flex-direction: row; + gap: ${({ theme }) => theme.spaceMap.md}px; + align-items: start; + position: relative; + + &:not(:last-child) ${Number}:after { + content: ''; + position: absolute; + top: 28px; + bottom: -12px; + width: 1px; + background: var(--lido-color-border); + } +`; + +export const StepContent = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; + flex: 1 0 40%; + text-align: left; + + h3 { + color: var(--lido-color-text); + font-size: 14px; + font-weight: 700; + line-height: 24px; + } + + p { + color: var(--lido-color-textSecondary); + font-size: 12px; + font-weight: 400; + line-height: 20px; + } +`; + +export const ScoreAccordionstyle = styled(AccordionNavigatable)` + margin: 0; + & > [type='button'] { + padding: 0; + min-height: 24px; + } + & > [type='button'] + div > div { + padding: 4px 0 0; + } + + p, + ul, + ol { + margin: 0; + } +`; + +export const CategoryItemsWrapper = styled(StackStyle).attrs({ + $direction: 'column', +})<{ $offset?: keyof Theme['spaceMap'] }>` + position: relative; + padding-left: ${({ theme, $offset = 'xl' }) => theme.spaceMap[$offset]}px; + + &:before { + content: ''; + display: block; + position: absolute; + width: 2px; + height: 100%; + left: 0px; + background: var(--lido-color-border); + border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px; + } +`; diff --git a/features/ics/shared/consts.tsx b/features/ics/shared/consts.tsx new file mode 100644 index 000000000..ee90f8956 --- /dev/null +++ b/features/ics/shared/consts.tsx @@ -0,0 +1,54 @@ +import { format } from 'date-fns'; + +type IcsRound = { + round: number; + start: Date; + assessedDate: string; +}; + +export const ICS_ROUNDS: IcsRound[] = [ + { + round: 4, + start: new Date(`2026-01-22`), + assessedDate: `Q1-Q2\u00A02026`, + }, + { + round: 5, + start: new Date(`2026-04-14`), + assessedDate: `June\u00A008, 2026`, + }, + { + round: 6, + start: new Date(`2026-06-08`), + assessedDate: `September\u00A007, 2026`, + }, + { + round: 7, + start: new Date(`2026-09-07`), + assessedDate: `December\u00A007, 2026`, + }, + { + round: 8, + start: new Date(`2026-12-07`), + assessedDate: `late Q4 2026, or Q1 2027`, + }, +]; + +const formatIcsRoundDate = (date: Date) => format(date, 'MMMM\u00A0dd, yyyy'); + +const getCurrentRound = () => { + const now = new Date(); + const current = + ICS_ROUNDS.findLast((round) => now >= round.start) || + ICS_ROUNDS[ICS_ROUNDS.length - 1]; + const next = ICS_ROUNDS.find(({ round }) => round === current.round + 1); + + return { + ...current, + startDate: formatIcsRoundDate(current.start), + assessedDate: next ? formatIcsRoundDate(next.start) : current.assessedDate, + isPreciseAssessedDate: !!next, + }; +}; + +export const ICS_ROUND = getCurrentRound(); diff --git a/features/ics/shared/ics-providers.tsx b/features/ics/shared/ics-providers.tsx new file mode 100644 index 000000000..d25d61097 --- /dev/null +++ b/features/ics/shared/ics-providers.tsx @@ -0,0 +1,9 @@ +import { SurveysAuthProvider } from 'modules/surveys-sdk'; +import { FC, PropsWithChildren } from 'react'; +import { IcsStateProvider } from './ics-state-provider'; + +export const IcsProviders: FC = ({ children }) => ( + + {children} + +); diff --git a/features/ics/shared/ics-state-provider.tsx b/features/ics/shared/ics-state-provider.tsx new file mode 100644 index 000000000..a7803b8be --- /dev/null +++ b/features/ics/shared/ics-state-provider.tsx @@ -0,0 +1,95 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { + useIcsProof, + useNodeOperatorId, + useOperatorOwner, + useOperatorType, +} from 'modules/web3'; +import { endpoints, useSurveysQuery } from 'modules/surveys-sdk'; +import { + createContext, + FC, + PropsWithChildren, + useContext, + useMemo, + useState, +} from 'react'; +import invariant from 'tiny-invariant'; +import { IcsResponseDto } from './types'; + +export type TypeStatus = 'PENDING' | 'ISSUED' | 'OWNER_ISSUED' | 'CLAIMED'; + +type IcsStateContextType = { + typeStatus: TypeStatus; + data?: IcsResponseDto; + isPending: boolean; + isTypePending: boolean; + applyMode: boolean; + reset: (value?: boolean) => void; +}; + +const IcsStateContext = createContext( + {} as IcsStateContextType, +); + +export const useIcsState = () => { + const context = useContext(IcsStateContext); + invariant(context, 'Attempt to use `useIcsState` outside of provider'); + return context; +}; + +export const IcsStateProvider: FC = ({ children }) => { + const operatorId = useNodeOperatorId(); + const { data: operatorType } = useOperatorType(operatorId); + const { data: owner } = useOperatorOwner(operatorId); + + const { data: proofData, isPending: isTypePending } = useIcsProof(); + const { data: ownerProofData, isPending: isOwnerTypePending } = useIcsProof( + owner?.address, + ); + const { data, isPending } = useSurveysQuery( + endpoints.icsStatus, + ); + + const [manualReset, setManualReset] = useState(false); + const applyMode = useMemo(() => manualReset || !data, [data, manualReset]); + + const typeStatus: TypeStatus = useMemo(() => { + if (operatorType === OPERATOR_TYPE.CSM_ICS || proofData?.isConsumed) + return 'CLAIMED'; + if (proofData?.proof) return 'ISSUED'; + if (ownerProofData?.proof) return 'OWNER_ISSUED'; + return 'PENDING'; + }, [ + operatorType, + ownerProofData?.proof, + proofData?.isConsumed, + proofData?.proof, + ]); + + const value: IcsStateContextType = useMemo( + () => ({ + typeStatus, + data, + isPending, + isTypePending: isTypePending || (!!owner?.address && isOwnerTypePending), + applyMode, + reset: (value = true) => setManualReset(value), + }), + [ + typeStatus, + data, + isPending, + isTypePending, + owner?.address, + isOwnerTypePending, + applyMode, + ], + ); + + return ( + + {children} + + ); +}; diff --git a/features/ics/shared/index.ts b/features/ics/shared/index.ts new file mode 100644 index 000000000..d81c2aac8 --- /dev/null +++ b/features/ics/shared/index.ts @@ -0,0 +1,5 @@ +export * from './ics-state-provider'; +export * from './ics-providers'; +export * from './score-data'; +export * from './types'; +export * from './consts'; diff --git a/features/ics/shared/score-data.tsx b/features/ics/shared/score-data.tsx new file mode 100644 index 000000000..7a4564770 --- /dev/null +++ b/features/ics/shared/score-data.tsx @@ -0,0 +1,354 @@ +import { ReactNode } from 'react'; +import styled from 'styled-components'; + +import EthStakerIcon from 'assets/icons/ics-scores/ethstaker.png'; +import StakeCatIcon from 'assets/icons/ics-scores/stakecat.png'; +import ObolIcon from 'assets/icons/ics-scores/obol.png'; +import SSVIcon from 'assets/icons/ics-scores/ssv.png'; +import CSMIcon from 'assets/icons/ics-scores/csm.png'; +import SDVTIcon from 'assets/icons/ics-scores/sdvt.png'; +import HumanPassportIcon from 'assets/icons/ics-scores/humal-passport.png'; +import CirclesIcon from 'assets/icons/ics-scores/circles.png'; +import DiscordIcon from 'assets/icons/ics-scores/discord.png'; +import XTwitterIcon from 'assets/icons/ics-scores/x.png'; +import AragonIcon from 'assets/icons/ics-scores/aragon.png'; +import SnapshotIcon from 'assets/icons/ics-scores/snapshot.png'; +import GalxeIcon from 'assets/icons/ics-scores/galxe.png'; +import HighSignalIcon from 'assets/icons/ics-scores/high-signal.png'; +import GitPOAPsIcon from 'assets/icons/ics-scores/git-poap.png'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { IcsScoresItem } from './types'; +import { MatomoLink } from 'shared/components'; + +export type ScoreSource = { + id: string; + title: string; + description: string; + min: number; + max: number; + items: ScoreItem[]; +}; + +export type ScoreItem = { + id: IcsScoresItem; + name: string; + icon: ReactNode; + points: number | string; + description: ReactNode; +}; + +const IconStyle = (styled.img<{ src: string }>).attrs(({ src }) => ({ + src, +}))` + display: flex; + flex-shrink: 0; + width: 32px; + height: 32px; + + border-radius: 100%; + outline: 1px solid var(--lido-color-border); + outline-offset: -1px; +`; + +export const TOTAL_SCORE_REQUIRED = 15; + +export const SCORE_SOURCES: ScoreSource[] = [ + { + id: 'proofOfExperience', + title: 'Proof-of-Experience', + description: + 'This group of proofs represents users experience in Ethereum validation', + min: 5, + max: 8, + items: [ + { + id: 'ethStaker', + name: 'EthStaker solo-stakers list', + icon: , + points: 6, + description: + 'Submitted address is present in the latest EthStaker Solo Stakers list as a deposit address, and not excluded following the a Sybil analysis of the list', + }, + { + id: 'stakeCat', + name: 'StakeCat solo-stakers list', + icon: , + points: 6, + description: + 'Submitted address is present in the latest StakeCat Solo Stakers list (Gnosischain-Solo-Stakers or Solo-Stakers-B), and not excluded following a Sybil analysis of the list', + }, + { + id: 'obolTechne', + name: 'Obol Techne', + icon: , + points: '4-6', + description: ( + <> + Submitted address has the Obol Techne credential assigned: +
          - 4 points for Base Credential +
          - 5 points for Bronze Credential +
          - 6 points for Silver Credential + + ), + }, + { + id: 'ssvVerified', + name: 'SSV Verified operators', + icon: , + points: 7, + description: + 'Submitted address is present in the SSV Verified Operators list and does not belong to a professional operator', + }, + { + id: 'csmTestnet', + name: 'CSM testnet participation', + icon: , + points: '4-5', + description: ( + <> + 4 points are assigned in case: +
          - Submitted address belongs to a Node Operator that has been + active on CSM Hoodi Testnet for at least 60 days +
          - Performance for the Node Operator is above the Performance + threshold over at least 60 days of activity. +
          5 points are assigned in case all the requirements from above + are met, and the application contains an address that has Circles + verification + + ), + }, + { + id: 'csmMainnet', + name: 'CSM mainnet participation', + icon: , + points: 6, + description: ( + <> + - Submitted address belongs to a Node Operator that has been active + on CSM Mainnet for at least 30 days +
          - Performance for the Node Operator is above the Performance + threshold in the latest performance oracle report + + ), + }, + { + id: 'sdvtTestnet', + name: 'SDVTM testnet participation', + icon: , + points: 5, + description: + 'Submitted address participated in and completed the entire duration of a Simple DVT testnet with Obol, SSV, or Safestake as a home or community staker', + }, + { + id: 'sdvtMainnet', + name: 'SDVTM mainnet participation', + icon: , + points: 7, + description: + 'Submitted address is actively participating as a home or community staker in the Lido Simple DVT Module on mainnet at the time of application submission', + }, + ], + }, + { + id: 'proofOfHumanity', + title: 'Proof-of-Humanity', + description: + 'This group of proofs allows users to earn a score by being verified by third-party platforms that apply their own rules for identifying real individuals', + min: 4, + max: 8, + items: [ + { + id: 'humanPassport', + name: 'Human passport', + icon: , + points: '3-8', + description: ( + <> + Submitted address has the corresponding score according to a{' '} + + Lido customized scoring system on Human Passport + + . For more details, follow{' '} + + the guide + + + ), + }, + { + id: 'circles', + name: 'Circles', + icon: , + points: 4, + description: ( + <> + Submitted address is verified via a dedicated{' '} + + Lido group on Circles + + . To be able to tie the Circles account to the ICS application, the + external account should be added. For more details, follow{' '} + + the guide + + + ), + }, + { + id: 'ssvHumanity', + name: 'SSV Verified operators', + icon: , + points: 3, + description: + 'Submitted address is present in the SSV Verified Operators list and does not belong to a professional operator', + }, + { + id: 'discord', + name: 'Discord', + icon: , + points: 2, + description: ( + <> + - Submitted account is registered no less than 1 year ago +
          - A unique message with the address applying to be included in + the list is published from this account to prove ownership + + ), + }, + { + id: 'twitter', + name: 'X', + icon: , + points: 1, + description: ( + <> + - Submitted account is registered no less than 1 year ago +
          - A unique message with the address applying to be included in + the list is published from this account to prove ownership + + ), + }, + ], + }, + { + id: 'proofOfEngagement', + title: 'Proof-of-Engagement', + description: + 'This group represents user engagement within the Ethereum and Lido ecosystems', + min: 2, + max: 7, + items: [ + { + id: 'aragonVotes', + name: 'Participation in Aragon Votes', + icon: , + points: 2, + description: ( + <> + Submitted addresses have voted at least twice, with more than 100 + LDO. Different addresses can be used for voting + + ), + }, + { + id: 'snapshotVotes', + name: 'Participation in Snapshot Votes', + icon: , + points: 1, + description: ( + <> + Submitted addresses have voted at least three times, with more than + 100 LDO. Different addresses can be used for voting + + ), + }, + { + id: 'lidoGalxe', + name: 'Lido Galxe score', + icon: , + points: '4-5', + description: ( + <> + Submitted address has a score on the{' '} + + Lido Galxe space + + : +
          - 4 points if 4 ≤ Lido Galxe score ≤ 10 +
          - 5 points if Lido Galxe score {'>'} 10 + + ), + }, + { + id: 'highSignal', + name: 'High Signal score', + icon: , + points: '2-5', + description: ( + <> + Submitted address has a score on the{' '} + + Lido + {' '} + or{' '} + + SSV + {' '} + High Signal space: +
          - 2 points if 30 ≤ High Signal score ≤ 40 +
          - 3 points if 40 {'<'} High Signal score ≤ 60 +
          - 4 points if 60 {'<'} High Signal score ≤ 80 +
          - 5 points if High Signal score {'>'} 80 +
          + Lido and SSV scores are not added together. The higher score is + used. +
          + For more details, follow{' '} + + the guide + + + ), + }, + { + id: 'gitPoaps', + name: 'GitPOAPs', + icon: , + points: 2, + description: + 'Submitted address has at least one GitPOAP for contribution to the staking-related public good applications selected by CSM Committee', + }, + ], + }, +]; diff --git a/features/ics/shared/types.ts b/features/ics/shared/types.ts new file mode 100644 index 000000000..9acb89dd9 --- /dev/null +++ b/features/ics/shared/types.ts @@ -0,0 +1,60 @@ +export type IcsFormStatus = 'APPROVED' | 'REJECTED' | 'REVIEW'; + +export type IcsFormDataDto = { + mainAddress: string; + twitterLink?: string; + discordLink?: string; + additionalAddresses?: string[]; +}; + +export type IcsCommentsDto = { + reason?: string; + mainAddress?: string; + twitterLink?: string; + discordLink?: string; + additionalAddresses?: (string | null)[]; +}; + +export type IcsScoresDto = { + ethStaker?: number; + stakeCat?: number; + obolTechne?: number; + ssvVerified?: number; + csmTestnet?: number; + csmMainnet?: number; + sdvtTestnet?: number; + sdvtMainnet?: number; + humanPassport?: number; + circles?: number; + ssvHumanity?: number; + discord?: number; + twitter?: number; + aragonVotes?: number; + snapshotVotes?: number; + lidoGalxe?: number; + highSignal?: number; + gitPoaps?: number; +}; + +export type IcsScoresItem = keyof IcsScoresDto; + +export type IcsResponseDto = { + form: IcsFormDataDto; + status: IcsFormStatus; + comments: IcsCommentsDto; + scores: IcsScoresDto; + createdAt: string; + updatedAt: string | null; +}; + +export type IcsAdditionalAddressDto = { + address: string; + signature: string; +}; + +export type IcsApplyDto = { + mainAddress: string; + additionalAddresses?: IcsAdditionalAddressDto[]; + twitterLink?: string; + discordLink?: string; +}; diff --git a/features/ics/siwe-sign-in/index.ts b/features/ics/siwe-sign-in/index.ts new file mode 100644 index 000000000..6e79f6c72 --- /dev/null +++ b/features/ics/siwe-sign-in/index.ts @@ -0,0 +1 @@ +export * from './siwe-sign-in'; diff --git a/features/ics/siwe-sign-in/siwe-sign-in.tsx b/features/ics/siwe-sign-in/siwe-sign-in.tsx new file mode 100644 index 000000000..fa5571619 --- /dev/null +++ b/features/ics/siwe-sign-in/siwe-sign-in.tsx @@ -0,0 +1,42 @@ +import { Block, Button, Text } from '@lidofinance/lido-ui'; +import { useDappStatus } from 'modules/web3'; +import { FC } from 'react'; +import { InputAddress, Stack } from 'shared/components'; +import { useSiweAuth } from 'modules/siwe'; + +export const SiweSignIn: FC = () => { + const { address } = useDappStatus(); + const { signIn } = useSiweAuth(); + + return ( + + + + + Sign in + + + To continue, please sign a message with your connected address to + prove ownership + + + + + You are requesting ICS operator type for the following address: + + + + + + + + ); +}; diff --git a/features/metadata/index.ts b/features/metadata/index.ts new file mode 100644 index 000000000..1ca582da0 --- /dev/null +++ b/features/metadata/index.ts @@ -0,0 +1 @@ +export { MetadataPage } from './metadata-page'; diff --git a/features/metadata/metadata-form/context/index.ts b/features/metadata/metadata-form/context/index.ts new file mode 100644 index 000000000..aeac201f6 --- /dev/null +++ b/features/metadata/metadata-form/context/index.ts @@ -0,0 +1,4 @@ +export * from './metadata-data-provider'; +export * from './metadata-form-provider'; +export * from './types'; +export * from './use-metadata-flow'; diff --git a/features/metadata/metadata-form/context/metadata-data-provider.tsx b/features/metadata/metadata-form/context/metadata-data-provider.tsx new file mode 100644 index 000000000..fce9d2d5b --- /dev/null +++ b/features/metadata/metadata-form/context/metadata-data-provider.tsx @@ -0,0 +1,47 @@ +import { + KEY_OPERATOR_METADATA, + useNodeOperatorId, + useOperatorIsOwner, + useOperatorMetadata, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { FormDataContext, useFormData } from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import type { MetadataFormNetworkData } from './types'; + +const useMetadataFormNetworkData = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: metadata, isPending } = useOperatorMetadata(nodeOperatorId); + const { data: isOwner, isPending: isOwnerPending } = + useOperatorIsOwner(nodeOperatorId); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([KEY_OPERATOR_METADATA]); + }, [invalidate]); + + return { + data: { + nodeOperatorId, + currentName: metadata?.name, + currentDescription: metadata?.description, + ownerEditsRestricted: metadata?.ownerEditsRestricted, + isOwner, + } as MetadataFormNetworkData, + isPending: isPending || isOwnerPending, + revalidate, + }; +}; + +export const useMetadataFormData = useFormData; + +export const MetadataDataProvider: FC = ({ children }) => { + const networkData = useMetadataFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/metadata/metadata-form/context/metadata-form-provider.tsx b/features/metadata/metadata-form/context/metadata-form-provider.tsx new file mode 100644 index 000000000..8eeef2490 --- /dev/null +++ b/features/metadata/metadata-form/context/metadata-form-provider.tsx @@ -0,0 +1,42 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormControllerProvider, + useFlowSubmit, + useFormDefaultValues, +} from 'shared/hook-form/form-controller'; +import type { MetadataFormInputType, MetadataFormNetworkData } from './types'; +import { useMetadataFlowResolver } from './use-metadata-flow'; +import { useMetadataValidation } from './use-metadata-validation'; + +export const MetadataFormProvider: FC = ({ children }) => { + const resolver = useMetadataValidation(); + + const defaultValues = useFormDefaultValues< + MetadataFormInputType, + MetadataFormNetworkData + >((data) => ({ + name: data.currentName ?? '', + description: data.currentDescription ?? '', + })); + + const formObject = useForm({ + defaultValues, + resolver, + mode: 'onChange', + }); + + const submitter = useFlowSubmit(useMetadataFlowResolver()); + + return ( + + + {children} + + + ); +}; diff --git a/features/metadata/metadata-form/context/types.ts b/features/metadata/metadata-form/context/types.ts new file mode 100644 index 000000000..09c8d718e --- /dev/null +++ b/features/metadata/metadata-form/context/types.ts @@ -0,0 +1,14 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; + +export type MetadataFormInputType = { + name: string; + description: string; +}; + +export type MetadataFormNetworkData = { + nodeOperatorId: NodeOperatorId; + currentName: string; + currentDescription: string; + ownerEditsRestricted: boolean; + isOwner: boolean; +}; diff --git a/features/metadata/metadata-form/context/use-metadata-flow.ts b/features/metadata/metadata-form/context/use-metadata-flow.ts new file mode 100644 index 000000000..78f05ba66 --- /dev/null +++ b/features/metadata/metadata-form/context/use-metadata-flow.ts @@ -0,0 +1,56 @@ +import { type MethodAccess, MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useCanPerform } from 'shared/hooks'; +import invariant from 'tiny-invariant'; +import { useTxModalStagesMetadata } from '../hooks/use-tx-modal-stages-metadata'; +import { useMetadataFormData } from './metadata-data-provider'; +import type { MetadataFormInputType, MetadataFormNetworkData } from './types'; + +export type MetadataFlow = + | { action: 'no-access'; access: MethodAccess } + | { action: 'restricted' } + | ({ action: 'update' } & Executable); + +export const useMetadataFlowResolver = (): FlowResolver< + MetadataFormInputType, + MetadataFormNetworkData, + MetadataFlow +> => { + const sdk = useSmSDK(MODULE_NAME.CM); + invariant(sdk, 'CM SDK is required'); + const [canUpdate, updateAccess] = useCanPerform( + sdk.metaRegistry, + 'setOperatorInfo', + ); + const buildCallback = useTxModalStagesMetadata(); + + return useCallback( + (input, data) => { + if (!canUpdate) return { action: 'no-access', access: updateAccess }; + if (data.ownerEditsRestricted) return { action: 'restricted' }; + + return { + action: 'update' as const, + submit: () => + sdk.metaRegistry.setOperatorInfo({ + nodeOperatorId: data.nodeOperatorId, + name: input.name, + description: input.description, + callback: buildCallback(input, data), + }), + }; + }, + [sdk.metaRegistry, canUpdate, updateAccess, buildCallback], + ); +}; + +export const useMetadataFlow = (): MetadataFlow => { + const resolve = useMetadataFlowResolver(); + const data = useMetadataFormData(true); + return resolve({} as MetadataFormInputType, data); +}; diff --git a/features/metadata/metadata-form/context/use-metadata-validation.ts b/features/metadata/metadata-form/context/use-metadata-validation.ts new file mode 100644 index 000000000..0b1721b4f --- /dev/null +++ b/features/metadata/metadata-form/context/use-metadata-validation.ts @@ -0,0 +1,37 @@ +import { + useFormValidation, + validateLength, + ValidationError, +} from 'shared/hook-form/validation'; +import type { MetadataFormInputType, MetadataFormNetworkData } from './types'; + +export const useMetadataValidation = () => { + return useFormValidation( + 'name', + async ( + { name, description }, + { currentName, currentDescription, ownerEditsRestricted }, + validate, + ) => { + await validate('name', () => { + validateLength('name', name, 1, 64); + }); + + await validate('description', () => { + validateLength('description', description, 1, 1024); + }); + + await validate('name', () => { + if (name === currentName && description === currentDescription) { + throw new ValidationError('name', 'No changes detected'); + } + }); + + await validate('name', () => { + if (ownerEditsRestricted) { + throw new ValidationError('name', 'Edits are restricted'); + } + }); + }, + ); +}; diff --git a/features/metadata/metadata-form/controls/description-input.tsx b/features/metadata/metadata-form/controls/description-input.tsx new file mode 100644 index 000000000..ebb79d9b6 --- /dev/null +++ b/features/metadata/metadata-form/controls/description-input.tsx @@ -0,0 +1,20 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { TextInputHookForm } from 'shared/hook-form/controls'; + +export const DescriptionInput: FC = () => { + return ( + + + + A short blurb about your operator. This description will be publicly + visible on-chain and can be updated later. + + + ); +}; diff --git a/features/metadata/metadata-form/controls/info.tsx b/features/metadata/metadata-form/controls/info.tsx new file mode 100644 index 000000000..324272861 --- /dev/null +++ b/features/metadata/metadata-form/controls/info.tsx @@ -0,0 +1,16 @@ +import { Input } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { FormTitle } from 'shared/components'; +import { useMetadataFormData } from '../context/metadata-data-provider'; + +export const Info: FC = () => { + const { currentName, currentDescription } = useMetadataFormData(true); + + return ( + <> + Node Operator name + + + + ); +}; diff --git a/features/metadata/metadata-form/controls/name-input.tsx b/features/metadata/metadata-form/controls/name-input.tsx new file mode 100644 index 000000000..da43a61fa --- /dev/null +++ b/features/metadata/metadata-form/controls/name-input.tsx @@ -0,0 +1,19 @@ +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { TextInputHookForm } from 'shared/hook-form/controls'; + +export const NameInput: FC = () => { + return ( + + + + This name will be publicly visible on-chain. You can update it later. + + + ); +}; diff --git a/features/metadata/metadata-form/controls/submit-button.tsx b/features/metadata/metadata-form/controls/submit-button.tsx new file mode 100644 index 000000000..7d69dc927 --- /dev/null +++ b/features/metadata/metadata-form/controls/submit-button.tsx @@ -0,0 +1,5 @@ +import { SubmitButtonHookForm } from 'shared/hook-form/controls'; + +export const SubmitButton = () => ( + Save +); diff --git a/features/metadata/metadata-form/hooks/use-tx-modal-stages-metadata.tsx b/features/metadata/metadata-form/hooks/use-tx-modal-stages-metadata.tsx new file mode 100644 index 000000000..471513fa6 --- /dev/null +++ b/features/metadata/metadata-form/hooks/use-tx-modal-stages-metadata.tsx @@ -0,0 +1,39 @@ +import { + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import type { + MetadataFormInputType, + MetadataFormNetworkData, +} from '../context/types'; + +export const useTxModalStagesMetadata = () => + useTxStages( + (transitStage) => ({ + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (_result: undefined, txHash) => + transitStage( + , + ), + }), + ); diff --git a/features/metadata/metadata-form/index.ts b/features/metadata/metadata-form/index.ts new file mode 100644 index 000000000..14b6e492c --- /dev/null +++ b/features/metadata/metadata-form/index.ts @@ -0,0 +1 @@ +export { MetadataForm } from './metadata-form'; diff --git a/features/metadata/metadata-form/metadata-form-loader.tsx b/features/metadata/metadata-form/metadata-form-loader.tsx new file mode 100644 index 000000000..89ab7e2fb --- /dev/null +++ b/features/metadata/metadata-form/metadata-form-loader.tsx @@ -0,0 +1,17 @@ +import { FC, PropsWithChildren } from 'react'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useMetadataFlow } from './context'; +import { Info } from './controls/info'; + +const MetadataFormGate: FC = ({ children }) => { + const flow = useMetadataFlow(); + const isReadOnly = + flow.action === 'no-access' || flow.action === 'restricted'; + return isReadOnly ? : <>{children}; +}; + +export const MetadataFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/metadata/metadata-form/metadata-form.tsx b/features/metadata/metadata-form/metadata-form.tsx new file mode 100644 index 000000000..d8d806917 --- /dev/null +++ b/features/metadata/metadata-form/metadata-form.tsx @@ -0,0 +1,28 @@ +import { FC, memo } from 'react'; + +import { FormBlock, FormTitle } from 'shared/components'; +import { Form } from 'shared/hook-form/form-controller'; +import { MetadataDataProvider, MetadataFormProvider } from './context'; +import { DescriptionInput } from './controls/description-input'; +import { NameInput } from './controls/name-input'; +import { SubmitButton } from './controls/submit-button'; +import { MetadataFormLoader } from './metadata-form-loader'; + +export const MetadataForm: FC = memo(() => { + return ( + + + + +
          + Node Operator name + + + + +
          +
          +
          +
          + ); +}); diff --git a/features/metadata/metadata-page.tsx b/features/metadata/metadata-page.tsx new file mode 100644 index 000000000..e363a52ce --- /dev/null +++ b/features/metadata/metadata-page.tsx @@ -0,0 +1,23 @@ +import { FC } from 'react'; +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { useWeb3Key } from 'shared/hooks'; +import { Layout } from 'shared/layout'; +import { SettingsPageSwitcher } from 'shared/navigate'; +import { MetadataForm } from './metadata-form'; + +export const MetadataPage: FC = () => { + const key = useWeb3Key(); + + return ( + + + + + + + ); +}; diff --git a/features/monitoring/attestation-rate-section/attestation-rate-section.tsx b/features/monitoring/attestation-rate-section/attestation-rate-section.tsx new file mode 100644 index 000000000..2bccde87e --- /dev/null +++ b/features/monitoring/attestation-rate-section/attestation-rate-section.tsx @@ -0,0 +1,95 @@ +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; +import { Block, InlineLoader, Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { DATA_UNAVAILABLE } from 'consts/text'; +import { + useDappStatus, + useNodeOperatorId, + useOperatorInfo, +} from 'modules/web3'; +import { FC } from 'react'; +import { IconTooltip, MatomoLink, Stack } from 'shared/components'; +import { formatDate, formatPercent } from 'utils'; +import { DiffBadge } from './diff-badge'; +import { Rate } from './styles'; +import { Tip } from './tip'; +import { usePerformanceApi } from './use-performance-api'; +import { PerformanceMetricMethodology } from './performance-metric-methodology'; + +export const AttestationRateSection: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: info } = useOperatorInfo(nodeOperatorId); + const { data, error } = usePerformanceApi(); + const { chainId } = useDappStatus(); + + const showThisSection = + chainId === CHAINS.Mainnet && (data || (info?.totalDepositedKeys ?? 0) > 0); + + if (!showThisSection) return null; + + return ( + + + + + + Unified Performance Rating + + {data && ( +
          + Monitoring frame: {formatDate(data.startTimestamp)} —{' '} + {formatDate(data.endTimestamp)} +
          + )} +
          + +
          + Data Source:{' '} + + MigaLabs + +
          + +
          +
          + {data ? ( + <> + + {formatPercent(data.operatorAttestationRate)} + + + + {data.status !== 'bad' + ? 'above Performance Threshold' + : 'below Performance Threshold'} + + + + + {data.status !== 'good' && } + + ) : error ? ( + + {DATA_UNAVAILABLE} + + ) : ( + + )} + +
          +
          + ); +}; diff --git a/features/monitoring/attestation-rate-section/diff-badge.tsx b/features/monitoring/attestation-rate-section/diff-badge.tsx new file mode 100644 index 000000000..ae808e5b9 --- /dev/null +++ b/features/monitoring/attestation-rate-section/diff-badge.tsx @@ -0,0 +1,20 @@ +import { FC } from 'react'; +import { RateStatus } from 'types'; +import { formatPercent } from 'utils'; +import { BadgeStyle } from './styles'; + +import { ReactComponent as DownIcon } from 'assets/icons/triangle-down.svg'; +import { ReactComponent as UpIcon } from 'assets/icons/triangle-up.svg'; + +export const DiffBadge: FC<{ + values: [number, number]; + status: RateStatus; +}> = ({ values, status }) => { + const diff = values[0] - values[1]; + return ( + + {diff > 0 ? : } + {formatPercent(Math.abs(diff))} + + ); +}; diff --git a/features/monitoring/attestation-rate-section/index.ts b/features/monitoring/attestation-rate-section/index.ts new file mode 100644 index 000000000..f483ef30f --- /dev/null +++ b/features/monitoring/attestation-rate-section/index.ts @@ -0,0 +1 @@ +export * from './attestation-rate-section'; diff --git a/features/monitoring/attestation-rate-section/performance-metric-methodology.tsx b/features/monitoring/attestation-rate-section/performance-metric-methodology.tsx new file mode 100644 index 000000000..31f0aeb9d --- /dev/null +++ b/features/monitoring/attestation-rate-section/performance-metric-methodology.tsx @@ -0,0 +1,92 @@ +import { Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { FC } from 'react'; +import { MatomoLink, Stack } from 'shared/components'; +import { + AccordionWrapper, + FormulaBadge, + FormulaOperator, + FormulaWrapper, +} from './styles'; + +export const PerformanceMetricMethodology: FC = () => { + return ( + + Unified performance metric methodology + + } + > + +

          + Performance of each key in CSM is calculated based on three + parameters: +

          + +
            +
          • + Attestations (Aeff) +
          • +
          • + Block proposals (Beff) +
          • +
          • + Sync committee participation (Seff) +
          • +
          + +

          The resulting formula for key performance looks as follows:

          + + + + Pkey + + = + + Ca + + × + + Aeff + + + + + Cb + + × + + Beff + + + + + Cs + + × + + Seff + + + +

          + Each parameter is multiplied by a corresponding coefficient (C + x) that determines the parameter weight in the formula. The + values of the effectiveness parameters are calculated based on the + ratio of expected versus successful duties performed during the + monitoring frame. The values of the coefficients (which can vary per + Operator Type) are based on the weighting coefficients for these + duties in Ethereum's Consensus Layer specification. Check out the + detailed information{' '} + + in the documentation + + . +

          +
          +
          + ); +}; diff --git a/features/monitoring/attestation-rate-section/styles.ts b/features/monitoring/attestation-rate-section/styles.ts new file mode 100644 index 000000000..06cb98a37 --- /dev/null +++ b/features/monitoring/attestation-rate-section/styles.ts @@ -0,0 +1,94 @@ +import { Accordion, Text } from '@lidofinance/lido-ui'; +import { StackStyle } from 'shared/components'; +import styled, { css } from 'styled-components'; +import { RateStatus } from 'types'; + +export const Rate = styled(Text).attrs({ size: 'lg', weight: 700 })` + flex: 0 0 auto; +`; + +export const TipWrapper = styled.div<{ $danger?: boolean }>` + border-radius: ${({ theme }) => theme.borderRadiusesMap.lg}px; + padding: 12px; + background: ${({ $danger = false }) => + $danger + ? 'rgba(var(--lido-rgb-error), 0.1);' + : 'var(--lido-color-background)'}; + + color: ${({ $danger = false }) => + $danger ? 'var(--lido-color-error)' : 'var(--lido-color-textSecondary)'}; +`; + +const variants = { + good: css` + color: var(--lido-color-success); + background: rgba(var(--lido-rgb-success), 0.1); + `, + semi: css` + color: var(--lido-color-warning); + background: rgba(var(--lido-rgb-warning), 0.1); + `, + bad: css` + color: var(--lido-color-error); + background: rgba(var(--lido-rgb-error), 0.1); + `, +}; + +export const BadgeStyle = styled.div<{ $variant: RateStatus }>` + flex: 0 0 auto; + font-weight: 700; + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; + line-height: ${({ theme }) => theme.fontSizesMap.lg}px; + border-radius: ${({ theme }) => theme.borderRadiusesMap.xs}px; + padding: 2px 4px; + ${({ $variant }) => variants[$variant]} +`; + +// PerformanceMetricMethodology styles + +export const AccordionWrapper = styled(Accordion)` + background: var(--lido-color-backgroundSecondary); + border-radius: ${({ theme }) => theme.borderRadiusesMap.lg}px; + + & > div:first-child { + padding: ${({ theme }) => theme.spaceMap.lg}px; + } + + & > div + div > div { + padding: 0 ${({ theme }) => theme.spaceMap.lg}px + ${({ theme }) => theme.spaceMap.lg}px + ${({ theme }) => theme.spaceMap.lg}px; + } + + & > div + div > div > div { + color: var(--lido-color-text); + line-height: 20px; + } + + p, + ul { + margin: 0; + } + + sub { + line-height: 13px; + } +`; + +export const FormulaWrapper = styled(StackStyle).attrs({ + $gap: 'xs', + $align: 'center', +})` + flex-wrap: wrap; +`; + +export const FormulaBadge = styled.span` + background: var(--lido-color-borderLight); + border-radius: ${({ theme }) => theme.borderRadiusesMap.xs}px; + padding: 4px 8px; +`; + +export const FormulaOperator = styled.span` + font-size: ${({ theme }) => theme.fontSizesMap.sm}px; + padding: 0 2px; +`; diff --git a/features/monitoring/attestation-rate-section/tip.tsx b/features/monitoring/attestation-rate-section/tip.tsx new file mode 100644 index 000000000..b0711c8e9 --- /dev/null +++ b/features/monitoring/attestation-rate-section/tip.tsx @@ -0,0 +1,19 @@ +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { PERFORMANCE_TIPS_LINK } from 'consts/external-links'; +import { FC } from 'react'; +import { MatomoLink } from 'shared/components'; +import { TipWrapper } from './styles'; + +export const Tip: FC<{ danger?: boolean }> = ({ danger = false }) => ( + + Check out{' '} + + tips + {' '} + on how to improve your performance + +); diff --git a/features/monitoring/attestation-rate-section/use-performance-api.ts b/features/monitoring/attestation-rate-section/use-performance-api.ts new file mode 100644 index 000000000..bbda15b75 --- /dev/null +++ b/features/monitoring/attestation-rate-section/use-performance-api.ts @@ -0,0 +1,51 @@ +import { NodeOperatorId, PERCENT_BASIS } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { API_ROUTES, STRATEGY_LAZY } from 'consts'; +import { useNodeOperatorId } from 'modules/web3'; +import { Performance, RateStatus, UnifiedPerformance } from 'types'; +import { standardFetcher } from 'utils'; + +const usePerformanceRate = (nodeOperatorId?: NodeOperatorId) => { + const BASE_URL = typeof window === 'undefined' ? '' : window.location.origin; + const url = `${BASE_URL}/${API_ROUTES.PERFORMANCE}?node-operator-id=${nodeOperatorId}`; + + return useQuery({ + queryKey: ['performance', { nodeOperatorId }], + queryFn: async () => standardFetcher(url), + enabled: nodeOperatorId !== undefined, + ...STRATEGY_LAZY, + }); +}; + +export const usePerformanceApi = () => { + const nodeOperatorId = useNodeOperatorId(); + const queryRateApi = usePerformanceRate(nodeOperatorId); + // const queryPerfLeeway = usePerfLeeway(); // FIXME: use perf leeway + + const data = queryRateApi.data; + const leeway = 500; // queryPerfLeeway.data; + + return useQuery({ + queryKey: ['performance-api', nodeOperatorId, data, leeway], + queryFn: (): Performance | undefined => { + if (!data || !leeway) return undefined; + const offset = leeway / Number(PERCENT_BASIS); + const threshold = data.overallAttestationRate - offset; + const status: RateStatus = + data.operatorAttestationRate <= threshold + ? 'bad' + : data.operatorAttestationRate > + data.overallAttestationRate - offset / 2 + ? 'good' + : 'semi'; + + return { + ...data, + threshold, + status, + }; + }, + enabled: !!data && !!leeway, + ...STRATEGY_LAZY, + }); +}; diff --git a/features/monitoring/external-section/external-section.tsx b/features/monitoring/external-section/external-section.tsx new file mode 100644 index 000000000..3e075ea61 --- /dev/null +++ b/features/monitoring/external-section/external-section.tsx @@ -0,0 +1,19 @@ +import { FC } from 'react'; +import { SectionBlock, Stack, ExternalButtonLink } from 'shared/components'; +import { useExternalButtons } from './use-external-button'; + +export const ExternalSection: FC = () => { + const buttons = useExternalButtons(); + + if (buttons.length === 0) return null; + + return ( + + + {buttons.map((button) => ( + + ))} + + + ); +}; diff --git a/features/dashboard/external/index.ts b/features/monitoring/external-section/index.ts similarity index 100% rename from features/dashboard/external/index.ts rename to features/monitoring/external-section/index.ts diff --git a/features/monitoring/external-section/use-external-button.tsx b/features/monitoring/external-section/use-external-button.tsx new file mode 100644 index 000000000..315231027 --- /dev/null +++ b/features/monitoring/external-section/use-external-button.tsx @@ -0,0 +1,94 @@ +import { ComponentProps, useMemo } from 'react'; +import { type ExternalButtonLink } from 'shared/components'; + +import { ReactComponent as BeaconchaIcon } from 'assets/icons/beaconcha.svg'; +import { ReactComponent as MigaLabsIcon } from 'assets/icons/migalabs.svg'; +import { ReactComponent as LidoIcon } from 'assets/icons/lido.svg'; +import { ReactComponent as RatedIcon } from 'assets/icons/rated.svg'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { + useBeaconchainDashboardLink, + useMigaLabsLink, + useFeesMonitoningLink, + useOperatorPortalLink, + useRatedLink, + useBeaconchainEntityLink, +} from 'shared/hooks'; + +export const useExternalButtons = () => { + const beaconchainEntityLink = useBeaconchainEntityLink(); + const beaconchainDashboardLink = useBeaconchainDashboardLink(); + const feesMonitoningLink = useFeesMonitoningLink(); + const operatorPortalLink = useOperatorPortalLink(); + const ratedLink = useRatedLink(); + const migaLabsLink = useMigaLabsLink(); + + return useMemo( + (): ComponentProps[] => + [ + beaconchainEntityLink && { + title: 'beaconcha.in Entity', + 'data-testid': 'monitoringBeaconchainEntityLink', + icon: , + href: beaconchainEntityLink, + matomoEvent: + MATOMO_CLICK_EVENTS_TYPES.dashboardExternalBeaconchaEntityLink, + children: 'Overview of your operator on beaconcha.in', + }, + ratedLink && { + title: 'Rated explorer', + 'data-testid': 'monitoringRatedExplorerLink', + icon: , + href: ratedLink, + matomoEvent: MATOMO_CLICK_EVENTS_TYPES.dashboardExternalRatedLink, + children: + 'Provides effectiveness ratings, APRs and other useful metrics', + }, + migaLabsLink && { + title: 'MigaLabs', + 'data-testid': 'monitoringMigaLabsLink', + icon: , + href: migaLabsLink, + matomoEvent: MATOMO_CLICK_EVENTS_TYPES.dashboardExternalMigaLabsLink, + children: + 'Provides real-time statistics of your validators’ performance', + }, + beaconchainDashboardLink && { + title: 'beaconcha.in v2', + 'data-testid': 'monitoringBeaconchainV2Link', + icon: , + href: beaconchainDashboardLink, + matomoEvent: MATOMO_CLICK_EVENTS_TYPES.dashboardExternalBeaconchaLink, + children: + 'Dashboard displays statistics of your validators (up to 20 in free plan)', + }, + operatorPortalLink && { + title: 'Lido Operators Portal', + 'data-testid': 'monitoringOperatorsPortalLink', + icon: , + href: operatorPortalLink, + matomoEvent: + MATOMO_CLICK_EVENTS_TYPES.dashboardExternalOperatorsPortalLink, + children: 'Shows details about invalid keys', + }, + feesMonitoningLink && { + title: 'Lido Fees monitoring', + 'data-testid': 'monitoringFeesLink', + icon: , + href: feesMonitoningLink, + matomoEvent: + MATOMO_CLICK_EVENTS_TYPES.dashboardExternalFeesMonitoringLink, + children: + 'Tracks missed slots and blocks with incorrect fee recipient/MEV relays', + }, + ].filter((n) => !!n), + [ + beaconchainEntityLink, + ratedLink, + migaLabsLink, + beaconchainDashboardLink, + operatorPortalLink, + feesMonitoningLink, + ], + ); +}; diff --git a/features/monitoring/index.ts b/features/monitoring/index.ts new file mode 100644 index 000000000..424b13595 --- /dev/null +++ b/features/monitoring/index.ts @@ -0,0 +1 @@ +export * from './monitoring-page'; diff --git a/features/monitoring/monitoring-page.tsx b/features/monitoring/monitoring-page.tsx new file mode 100644 index 000000000..231c1db83 --- /dev/null +++ b/features/monitoring/monitoring-page.tsx @@ -0,0 +1,18 @@ +import { FC } from 'react'; +import { Layout } from 'shared/layout'; +import { Monitoring } from './monitoring'; +import { Faq } from 'shared/components'; +import { FAQ_MONITORING } from 'faq'; + +export const MonitoringPage: FC = () => { + return ( + + + + + ); +}; diff --git a/features/monitoring/monitoring.tsx b/features/monitoring/monitoring.tsx new file mode 100644 index 000000000..b3b1609a1 --- /dev/null +++ b/features/monitoring/monitoring.tsx @@ -0,0 +1,20 @@ +import { FC } from 'react'; +import { NoSSRWrapper } from 'shared/components'; +import { ExternalSection } from './external-section'; +import { NotificationToolsSection } from './notification-tools-section'; +import { StrikesSection } from './strikes-section'; +import { AttestationRateSection } from './attestation-rate-section'; +import { isModuleCSM } from 'consts'; + +export const Monitoring: FC = () => { + return ( + <> + + {isModuleCSM && } + {isModuleCSM && } + + {isModuleCSM && } + + + ); +}; diff --git a/features/monitoring/notification-tools-section/index.ts b/features/monitoring/notification-tools-section/index.ts new file mode 100644 index 000000000..be05cf8c1 --- /dev/null +++ b/features/monitoring/notification-tools-section/index.ts @@ -0,0 +1 @@ +export { NotificationToolsSection } from './notification-tools-section'; diff --git a/features/monitoring/notification-tools-section/notification-tools-buttons.tsx b/features/monitoring/notification-tools-section/notification-tools-buttons.tsx new file mode 100644 index 000000000..818152868 --- /dev/null +++ b/features/monitoring/notification-tools-section/notification-tools-buttons.tsx @@ -0,0 +1,17 @@ +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { ComponentProps } from 'react'; +import { ExternalButtonLink } from 'shared/components'; +import { ReactComponent as CsmIcon } from 'assets/icons/csm.svg'; + +export const NOTIFICATION_TOOLS_BUTTONS: ComponentProps< + typeof ExternalButtonLink +>[] = [ + { + title: 'CSM Sentinel', + 'data-testid': 'monitoringCsmSentinelLink', + icon: , + href: 'https://github.com/skhomuti/csm-sentinel', + matomoEvent: MATOMO_CLICK_EVENTS_TYPES.dashboardNotificationSentinelLink, + children: 'Provides your CSM Node Operator events to the telegram chats', + }, +]; diff --git a/features/monitoring/notification-tools-section/notification-tools-section.tsx b/features/monitoring/notification-tools-section/notification-tools-section.tsx new file mode 100644 index 000000000..5db45d159 --- /dev/null +++ b/features/monitoring/notification-tools-section/notification-tools-section.tsx @@ -0,0 +1,17 @@ +import { FC } from 'react'; +import { SectionBlock, Stack, ExternalButtonLink } from 'shared/components'; +import { NOTIFICATION_TOOLS_BUTTONS } from './notification-tools-buttons'; + +export const NotificationToolsSection: FC = () => { + if (NOTIFICATION_TOOLS_BUTTONS.length === 0) return null; + + return ( + + + {NOTIFICATION_TOOLS_BUTTONS.map((button) => ( + + ))} + + + ); +}; diff --git a/features/monitoring/strikes-section/index.ts b/features/monitoring/strikes-section/index.ts new file mode 100644 index 000000000..68d345df9 --- /dev/null +++ b/features/monitoring/strikes-section/index.ts @@ -0,0 +1 @@ +export * from './strikes-section'; diff --git a/features/monitoring/strikes-section/last-strike.tsx b/features/monitoring/strikes-section/last-strike.tsx new file mode 100644 index 000000000..658bd7d0c --- /dev/null +++ b/features/monitoring/strikes-section/last-strike.tsx @@ -0,0 +1,19 @@ +import { InlineLoader, Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { useStrikeDates } from 'shared/hooks'; +import { formatDate } from 'utils'; + +export const LastStrike: FC<{ strikes: number[] }> = ({ strikes }) => { + const n = strikes.findIndex((v) => !!v); + const dates = useStrikeDates(n); + + if (!dates) { + return ; + } + + return ( + + Last Strike: {formatDate(dates?.receivedTimestamp, 'dd.MM.yyyy')} + + ); +}; diff --git a/features/monitoring/strikes-section/strikes-section.tsx b/features/monitoring/strikes-section/strikes-section.tsx new file mode 100644 index 000000000..d1a8d2ea5 --- /dev/null +++ b/features/monitoring/strikes-section/strikes-section.tsx @@ -0,0 +1,44 @@ +import { KEY_STATUS, KeyWithStatus } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { useNodeOperatorId, useOperatorKeysWithStatus } from 'modules/web3'; +import { FC } from 'react'; +import { + FaqStrikeLifetime, + FaqStrikeThreshold, + SectionBlock, + Stack, +} from 'shared/components'; +import { TablePagination, TableProvider } from 'providers/table-provider'; +import { hasStatus } from 'utils'; +import { StrikesTable } from './strikes-table'; + +type WithStrikes = KeyWithStatus & Required>; + +export const StrikesSection: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data: keys } = useOperatorKeysWithStatus(nodeOperatorId, (data) => { + return data + .filter(hasStatus(KEY_STATUS.WITH_STRIKES)) + .filter( + hasStatus([KEY_STATUS.ACTIVE, KEY_STATUS.ACTIVATION_PENDING]), + ) as WithStrikes[]; + }); + + if (!keys?.length) return null; + + return ( + + + + + Strikes are issued for bad performance. In case your key gets{' '} + within the key will be + ejected. + + + + + + + ); +}; diff --git a/features/monitoring/strikes-section/strikes-table.tsx b/features/monitoring/strikes-section/strikes-table.tsx new file mode 100644 index 000000000..fd9befb2a --- /dev/null +++ b/features/monitoring/strikes-section/strikes-table.tsx @@ -0,0 +1,24 @@ +import { KeyWithStatus } from '@lidofinance/lido-csm-sdk'; +import { FC } from 'react'; +import { KeyStrikes, Pubkey, PubkeyLinks } from 'shared/components'; +import { useTable } from 'providers/table-provider'; +import { LastStrike } from './last-strike'; +import { List, Row } from './styles'; + +type WithStrikes = KeyWithStatus & Required>; + +export const StrikesTable: FC = () => { + const { data } = useTable(); + + return ( + + {data.map((key) => ( + + } /> + + + + ))} + + ); +}; diff --git a/features/monitoring/strikes-section/styles.ts b/features/monitoring/strikes-section/styles.ts new file mode 100644 index 000000000..f560e83a8 --- /dev/null +++ b/features/monitoring/strikes-section/styles.ts @@ -0,0 +1,58 @@ +import styled from 'styled-components'; + +export const List = styled.div` + display: flex; + flex-direction: column; + gap: 0; + > * { + position: relative; + + :not(:first-child) { + :before { + content: ''; + position: absolute; + top: 0px; + left: 0; + width: 100%; + height: 1px; + background: var(--lido-color-popupMenuItemBgActiveHover); + opacity: 0.12; + } + } + } +`; + +export const Row = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + gap: 6px; + padding: 12px 0; + + ${({ theme }) => theme.mediaQueries.lg} { + display: grid; + grid-auto-rows: auto; + grid-column-gap: 1rem; + grid-template-columns: 2fr 1fr; + + td:nth-child(3) { + grid-column: 1 / -1; + + &:empty { + display: none; + } + } + + th:nth-child(3) { + display: none; + } + } + + ${({ theme }) => theme.mediaQueries.md} { + grid-template-columns: 1fr; + } + + > :last-child { + min-width: fit-content; + } +`; diff --git a/features/normalize-queue/normalize-queue-form/context/index.ts b/features/normalize-queue/normalize-queue-form/context/index.ts index 19d33b0b9..e85488bce 100644 --- a/features/normalize-queue/normalize-queue-form/context/index.ts +++ b/features/normalize-queue/normalize-queue-form/context/index.ts @@ -1,2 +1,4 @@ +export * from './normalize-queue-data-provider'; export * from './normalize-queue-form-provider'; export * from './types'; +export * from './use-normalize-queue-flow'; diff --git a/features/normalize-queue/normalize-queue-form/context/normalize-queue-data-provider.tsx b/features/normalize-queue/normalize-queue-form/context/normalize-queue-data-provider.tsx new file mode 100644 index 000000000..4229fac3b --- /dev/null +++ b/features/normalize-queue/normalize-queue-form/context/normalize-queue-data-provider.tsx @@ -0,0 +1,67 @@ +import { + KEY_OPERATOR_INFO, + useEthereumBalance, + useNodeOperatorId, + useOperatorInfo, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import { type NormalizeQueueFormNetworkData } from './types'; + +const useNormalizeQueueFormNetworkData: NetworkData< + NormalizeQueueFormNetworkData +> = () => { + const nodeOperatorId = useNodeOperatorId(); + + const infoQuery = useOperatorInfo(nodeOperatorId); + const ethBalanceQuery = useEthereumBalance(); + + const info = infoQuery.data; + const ethBalance = ethBalanceQuery.data; + + const isInfoLoading = infoQuery.isPending; + const isEthBalanceLoading = ethBalanceQuery.isPending; + + const unqueuedCount = info + ? info.depositableValidatorsCount - info.enqueuedCount + : undefined; + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([KEY_OPERATOR_INFO, ethBalanceQuery.queryKey]); + }, [invalidate, ethBalanceQuery.queryKey]); + + const isPending = isInfoLoading || isEthBalanceLoading; + + return { + data: { + nodeOperatorId, + info, + unqueuedCount, + ethBalance, + } as NormalizeQueueFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useNormalizeQueueFormData = + useFormData; + +export const NormalizeQueueDataProvider: FC = ({ + children, +}) => { + const networkData = useNormalizeQueueFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/normalize-queue/normalize-queue-form/context/normalize-queue-form-provider.tsx b/features/normalize-queue/normalize-queue-form/context/normalize-queue-form-provider.tsx index ee0b251c5..74a9934d0 100644 --- a/features/normalize-queue/normalize-queue-form/context/normalize-queue-form-provider.tsx +++ b/features/normalize-queue/normalize-queue-form/context/normalize-queue-form-provider.tsx @@ -1,61 +1,30 @@ -import { FC, PropsWithChildren, useMemo } from 'react'; +import { FC, PropsWithChildren } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormControllerRetry, - useFormData, + FormControllerProvider, + useFlowSubmit, } from 'shared/hook-form/form-controller'; -import { - NormalizeQueueFormNetworkData, - type NormalizeQueueFormInputType, -} from './types'; -import { useNormalizeQueueFormNetworkData } from './use-normalize-queue-form-network-data'; -import { useNormalizeQueueSubmit } from './use-normalize-queue-submit'; +import { type NormalizeQueueFormInputType } from './types'; +import { useNormalizeQueueFlowResolver } from './use-normalize-queue-flow'; import { useNormalizeQueueValidation } from './use-normalize-queue-validation'; -export const useNormalizeQueueFormData = - useFormData; - export const NormalizeQueueFormProvider: FC = ({ children, }) => { - const [networkData, revalidate] = useNormalizeQueueFormNetworkData(); - const validationResolver = useNormalizeQueueValidation(networkData); + const resolver = useNormalizeQueueValidation(); - // TODO: validate (max amount) const formObject = useForm({ - defaultValues: {}, - resolver: validationResolver, + resolver, mode: 'onChange', }); - const { retryEvent, retryFire } = useFormControllerRetry(); - - const { normalizeQueue } = useNormalizeQueueSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - NormalizeQueueFormInputType, - NormalizeQueueFormNetworkData - > = useMemo( - () => ({ - onSubmit: normalizeQueue, - retryEvent, - }), - [normalizeQueue, retryEvent], - ); + const submitter = useFlowSubmit(useNormalizeQueueFlowResolver()); return ( - - - {children} - - + + {children} + ); }; diff --git a/features/normalize-queue/normalize-queue-form/context/types.ts b/features/normalize-queue/normalize-queue-form/context/types.ts index 757d1de12..f989529fc 100644 --- a/features/normalize-queue/normalize-queue-form/context/types.ts +++ b/features/normalize-queue/normalize-queue-form/context/types.ts @@ -1,13 +1,10 @@ -import { BigNumber } from 'ethers'; -import { useNodeOperatorInfo } from 'shared/hooks'; -import { LoadingRecord, NodeOperatorId } from 'types'; +import { NodeOperatorId, NodeOperatorInfo } from '@lidofinance/lido-csm-sdk'; export type NormalizeQueueFormInputType = Record; export type NormalizeQueueFormNetworkData = { - nodeOperatorId?: NodeOperatorId; - info?: ReturnType['data']; - unqueuedCount?: number; - etherBalance?: BigNumber; - loading: LoadingRecord<'info' | 'etherBalance'>; + nodeOperatorId: NodeOperatorId; + info: NodeOperatorInfo; + unqueuedCount: number; + ethBalance: bigint; }; diff --git a/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-flow.ts b/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-flow.ts new file mode 100644 index 000000000..d54fbadbe --- /dev/null +++ b/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-flow.ts @@ -0,0 +1,54 @@ +import { type MethodAccess, MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useCanPerform } from 'shared/hooks'; +import invariant from 'tiny-invariant'; +import { useTxModalStagesNormalizeQueue } from '../hooks/use-tx-modal-stages-normalize-queue'; +import { useNormalizeQueueFormData } from './normalize-queue-data-provider'; +import { + NormalizeQueueFormInputType, + NormalizeQueueFormNetworkData, +} from './types'; + +export type NormalizeQueueFlow = + | { action: 'no-access'; access: MethodAccess } + | { action: 'nothing' } + | ({ action: 'normalize' } & Executable); + +export const useNormalizeQueueFlowResolver = (): FlowResolver< + NormalizeQueueFormInputType, + NormalizeQueueFormNetworkData, + NormalizeQueueFlow +> => { + const sdk = useSmSDK(MODULE_NAME.CSM); + invariant(sdk, 'CSM SDK is required'); + const [canNormalize, access] = useCanPerform(sdk.depositQueue, 'normalize'); + const buildCallback = useTxModalStagesNormalizeQueue(); + + return useCallback( + (input, data) => { + if (!canNormalize) return { action: 'no-access', access }; + if (data.unqueuedCount === 0) return { action: 'nothing' }; + + return { + action: 'normalize' as const, + submit: () => + sdk.depositQueue.normalize({ + nodeOperatorId: data.nodeOperatorId, + callback: buildCallback(input, data), + }), + }; + }, + [sdk.depositQueue, canNormalize, access, buildCallback], + ); +}; + +export const useNormalizeQueueFlow = (): NormalizeQueueFlow => { + const resolve = useNormalizeQueueFlowResolver(); + const data = useNormalizeQueueFormData(true); + return resolve({} as NormalizeQueueFormInputType, data); +}; diff --git a/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-form-network-data.tsx b/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-form-network-data.tsx deleted file mode 100644 index 448ad469a..000000000 --- a/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-form-network-data.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { useEthereumBalance } from '@lido-sdk/react'; -import { STRATEGY_LAZY } from 'consts/swr-strategies'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { useCallback, useMemo } from 'react'; -import { useNodeOperatorInfo } from 'shared/hooks'; -import { type NormalizeQueueFormNetworkData } from './types'; - -export const useNormalizeQueueFormNetworkData = (): [ - NormalizeQueueFormNetworkData, - () => Promise, -] => { - const nodeOperatorId = useNodeOperatorId(); - - const { - data: info, - update: updateInfo, - initialLoading: isInfoLoading, - } = useNodeOperatorInfo(nodeOperatorId); - - const unqueuedCount = info - ? info.depositableValidatorsCount - info.enqueuedCount - : undefined; - - const { - data: etherBalance, - update: updateEtherBalance, - initialLoading: isEtherBalanceLoading, - } = useEthereumBalance(undefined, STRATEGY_LAZY); - - const revalidate = useCallback(async () => { - await Promise.allSettled([updateInfo(), updateEtherBalance()]); - }, [updateEtherBalance, updateInfo]); - - const loading = useMemo( - () => ({ - isInfoLoading, - isEtherBalanceLoading, - }), - [isEtherBalanceLoading, isInfoLoading], - ); - - return [ - { - nodeOperatorId, - info, - unqueuedCount, - etherBalance, - loading, - }, - revalidate, - ]; -}; diff --git a/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-submit.ts b/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-submit.ts deleted file mode 100644 index 734271a5a..000000000 --- a/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-submit.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { useCallback } from 'react'; -import invariant from 'tiny-invariant'; - -import { useCSModuleWeb3, useSendTx } from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; -import { runWithTransactionLogger } from 'utils'; -import { NormalizeQueueFormInputType, NormalizeQueueFormNetworkData } from '.'; -import { useTxModalStagesNormalizeQueue } from '../hooks/use-tx-modal-stages-normalize-queue'; - -type UseNormalizeQueueOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type NormalizeQueueMethodParams = { - nodeOperatorId: NodeOperatorId; -}; - -const useNormalizeQueueTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async (params: NormalizeQueueMethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - return { - tx: await CSModuleWeb3.populateTransaction.normalizeQueue( - params.nodeOperatorId, - ), - txName: 'normalizeQueue', - }; - }, - [CSModuleWeb3], - ); -}; - -export const useNormalizeQueueSubmit = ({ - onConfirm, - onRetry, -}: UseNormalizeQueueOptions) => { - const { txModalStages } = useTxModalStagesNormalizeQueue(); - - const getTx = useNormalizeQueueTx(); - const sendTx = useSendTx(); - - const normalizeQueue = useCallback( - async ( - _: NormalizeQueueFormInputType, - { nodeOperatorId, info }: NormalizeQueueFormNetworkData, - ): Promise => { - invariant(nodeOperatorId, 'NodeOperatorId is not defined'); - invariant(info, 'Info is not defined'); - - try { - txModalStages.sign({ - keysCount: info.depositableValidatorsCount - info.enqueuedCount, - }); - - const tx = await getTx({ - nodeOperatorId, - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'NormalizeQueue signing', - () => sendTx(tx), - ); - - txModalStages.pending( - { - keysCount: info.depositableValidatorsCount - info.enqueuedCount, - }, - txHash, - ); - - await runWithTransactionLogger( - 'NormalizeQueue block confirmation', - waitTx, - ); - - await onConfirm?.(); - - txModalStages.success( - { keysCount: info.depositableValidatorsCount }, - txHash, - ); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [getTx, txModalStages, onConfirm, sendTx, onRetry], - ); - - return { - normalizeQueue, - }; -}; diff --git a/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-validation.ts b/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-validation.ts index 527099b07..5417be15f 100644 --- a/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-validation.ts +++ b/features/normalize-queue/normalize-queue-form/context/use-normalize-queue-validation.ts @@ -1,37 +1,17 @@ -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; -import { handleResolverValidationError } from 'shared/hook-form/validation'; -import { useAwaitNetworkData } from 'shared/hooks'; +import { useFormValidation } from 'shared/hook-form/validation'; import invariant from 'tiny-invariant'; import type { NormalizeQueueFormInputType, NormalizeQueueFormNetworkData, } from './types'; -export const useNormalizeQueueValidation = ( - networkData: NormalizeQueueFormNetworkData, -) => { - const dataPromise = useAwaitNetworkData(networkData); - - return useCallback>( - async (values) => { - try { - const { etherBalance } = await dataPromise; - - invariant(etherBalance); - - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError( - error, - 'NormalizeQueueForm', - 'keysCount', - ); - } - }, - [dataPromise], - ); +export const useNormalizeQueueValidation = () => { + return useFormValidation< + NormalizeQueueFormInputType, + NormalizeQueueFormNetworkData + >('keysCount', async (_, { ethBalance }, validate) => { + await validate('keysCount', () => { + invariant(ethBalance !== undefined, 'Insufficient ETH balance'); + }); + }); }; diff --git a/features/normalize-queue/normalize-queue-form/controls/info.tsx b/features/normalize-queue/normalize-queue-form/controls/info.tsx index 4d914df3e..0c2efe792 100644 --- a/features/normalize-queue/normalize-queue-form/controls/info.tsx +++ b/features/normalize-queue/normalize-queue-form/controls/info.tsx @@ -3,18 +3,11 @@ import { Latice, TitledValue } from 'shared/components'; import { useNormalizeQueueFormData } from '../context'; export const Info: FC = () => { - const { info, unqueuedCount, loading } = useNormalizeQueueFormData(); + const { unqueuedCount } = useNormalizeQueueFormData(); return ( <> - - {info?.stuckValidatorsCount ? ( - - ) : null} + ); diff --git a/features/normalize-queue/normalize-queue-form/controls/submit-button.tsx b/features/normalize-queue/normalize-queue-form/controls/submit-button.tsx index c56f6b9f6..b71585707 100644 --- a/features/normalize-queue/normalize-queue-form/controls/submit-button.tsx +++ b/features/normalize-queue/normalize-queue-form/controls/submit-button.tsx @@ -1,32 +1,18 @@ import { SubmitButtonHookForm } from 'shared/hook-form/controls'; -import { useNormalizeQueueFormData } from '../context'; +import { useNormalizeQueueFlow } from '../context'; import { Note } from 'shared/components'; export const SubmitButton = () => { - const { info, unqueuedCount } = useNormalizeQueueFormData(); + const flow = useNormalizeQueueFlow(); return ( <> - {unqueuedCount ? ( - info?.stuckValidatorsCount ? ( - <> - - You have stuck keys - - Before normalize queue you need to exit stuck keys - - ) : ( - <> - - Normalizing queue - + {flow.action === 'normalize' ? ( + <> + Normalizing queue - Or submit more keys - - ) + Or submit more keys + ) : ( No need to normalize queue diff --git a/features/normalize-queue/normalize-queue-form/hooks/use-tx-modal-stages-normalize-queue.tsx b/features/normalize-queue/normalize-queue-form/hooks/use-tx-modal-stages-normalize-queue.tsx index 80b585a00..7fece4e77 100644 --- a/features/normalize-queue/normalize-queue-form/hooks/use-tx-modal-stages-normalize-queue.tsx +++ b/features/normalize-queue/normalize-queue-form/hooks/use-tx-modal-stages-normalize-queue.tsx @@ -1,51 +1,45 @@ import { - TransactionModalTransitStage, TxStagePending, TxStageSign, TxStageSuccess, - getGeneralTransactionModalStages, - useTransactionModalStage, + useTxStages, } from 'shared/transaction-modal'; +import { + NormalizeQueueFormInputType, + NormalizeQueueFormNetworkData, +} from '../context/types'; -type Props = { - keysCount: number; -}; - -const getTxModalStagesNormalizeQueue = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: ({ keysCount }: Props) => - transitStage( - , - ), - - pending: ({ keysCount }: Props, txHash?: string) => - transitStage( - , - ), - - success: ({ keysCount }: Props, txHash?: string) => - transitStage( - , - { - isClosableOnLedger: true, - }, - ), -}); +const getKeysCount = (data: NormalizeQueueFormNetworkData) => + data.info.depositableValidatorsCount - data.info.enqueuedCount; -export const useTxModalStagesNormalizeQueue = () => { - return useTransactionModalStage(getTxModalStagesNormalizeQueue); -}; +export const useTxModalStagesNormalizeQueue = () => + useTxStages( + (transitStage, _input, data) => { + const keysCount = getKeysCount(data); + return { + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (_result: undefined, txHash) => + transitStage( + , + ), + }; + }, + ); diff --git a/features/normalize-queue/normalize-queue-form/normalize-queue-form-loader.tsx b/features/normalize-queue/normalize-queue-form/normalize-queue-form-loader.tsx index 994e0e72f..9eda4b335 100644 --- a/features/normalize-queue/normalize-queue-form/normalize-queue-form-loader.tsx +++ b/features/normalize-queue/normalize-queue-form/normalize-queue-form-loader.tsx @@ -1,12 +1,22 @@ import { FC, PropsWithChildren } from 'react'; -import { useFormState } from 'react-hook-form'; -import { WhenLoaded } from 'shared/components'; -import { NormalizeQueueFormInputType } from './context'; +import { NoAccessNotice } from 'shared/components'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useNormalizeQueueFlow } from './context'; -export const NormalizeQueueFormLoader: FC = ({ - children, -}) => { - const { isLoading } = useFormState(); +const NormalizeQueueFormGate: FC = ({ children }) => { + const flow = useNormalizeQueueFlow(); + + if (flow.action === 'no-access') { + return ; + } - return {children}; + return <>{children}; }; + +export const NormalizeQueueFormLoader: FC = ({ + children, +}) => ( + + {children} + +); diff --git a/features/normalize-queue/normalize-queue-form/normalize-queue-form.tsx b/features/normalize-queue/normalize-queue-form/normalize-queue-form.tsx index 01d1d98f6..a1695d5c3 100644 --- a/features/normalize-queue/normalize-queue-form/normalize-queue-form.tsx +++ b/features/normalize-queue/normalize-queue-form/normalize-queue-form.tsx @@ -1,9 +1,11 @@ import { FC, memo } from 'react'; -import { NormalizeQueueFormProvider } from './context'; - import { FormBlock } from 'shared/components'; -import { FormControllerStyled } from 'shared/hook-form/form-controller'; +import { Form } from 'shared/hook-form/form-controller'; +import { + NormalizeQueueDataProvider, + NormalizeQueueFormProvider, +} from './context'; import { Info } from './controls/info'; import { SubmitButton } from './controls/submit-button'; import { NormalizeQueueFormInfo } from './normalize-queue-form-info'; @@ -11,16 +13,18 @@ import { NormalizeQueueFormLoader } from './normalize-queue-form-loader'; export const NormalizeQueueForm: FC = memo(() => { return ( - - - - - - - - - - - + + + + +
          + + + + +
          +
          +
          +
          ); }); diff --git a/features/normalize-queue/normalize-queue-page.tsx b/features/normalize-queue/normalize-queue-page.tsx index a50ccb9d3..6747778f7 100644 --- a/features/normalize-queue/normalize-queue-page.tsx +++ b/features/normalize-queue/normalize-queue-page.tsx @@ -1,6 +1,5 @@ import { FC } from 'react'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; import { Layout } from 'shared/layout'; import { NormalizeQueue } from './normalize-queue'; @@ -8,7 +7,7 @@ export const NormalizeQueuePage: FC = () => ( diff --git a/features/normalize-queue/normalize-queue.tsx b/features/normalize-queue/normalize-queue.tsx index b709ba7d7..20ebcdc7e 100644 --- a/features/normalize-queue/normalize-queue.tsx +++ b/features/normalize-queue/normalize-queue.tsx @@ -1,5 +1,5 @@ import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; +import { useWeb3Key } from 'shared/hooks'; import { NormalizeQueueForm } from './normalize-queue-form'; diff --git a/features/operator-type/ics-type-card.tsx b/features/operator-type/ics-type-card.tsx new file mode 100644 index 000000000..190d4faee --- /dev/null +++ b/features/operator-type/ics-type-card.tsx @@ -0,0 +1,57 @@ +import { Text } from '@lidofinance/lido-ui'; +import { IcsApplyButton } from 'features/ics/apply-button'; +import { ScoreChip } from 'features/ics/form-status/components/score-chip'; +import { IcsFormStatus, TypeStatus, useIcsState } from 'features/ics/shared'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { OptionCard, TypeBadge } from './styles'; + +const renderStatusChip = ( + typeStatus: TypeStatus, + status: IcsFormStatus | undefined, +) => { + if (typeStatus === 'CLAIMED') { + return Claimed; + } + if (typeStatus === 'ISSUED') { + return Issued; + } + switch (status) { + case 'APPROVED': + return Approved; + case 'REJECTED': + return Rejected; + case 'REVIEW': + return Pending; + default: + return null; + } +}; + +export const IcsTypeCard: FC = () => { + const { typeStatus, data } = useIcsState(); + const chip = renderStatusChip(typeStatus, data?.status); + + return ( + + + + ICS + {chip} + + + + Identified Community Staker + + + Obtain enhanced validation parameters by becoming recognized as an + independent Community Staker. Please note that the verification + process takes time and requires the submission of specific + supporting proofs. + + + + + + ); +}; diff --git a/features/operator-type/idvtc-type-card.tsx b/features/operator-type/idvtc-type-card.tsx new file mode 100644 index 000000000..3edd8bd8f --- /dev/null +++ b/features/operator-type/idvtc-type-card.tsx @@ -0,0 +1,56 @@ +import { Text } from '@lidofinance/lido-ui'; +import { DvtApplyButton } from 'features/dvt/apply-button'; +import { ScoreChip } from 'features/dvt/form-status/components/score-chip'; +import { DvtFormStatus, DvtTypeStatus, useDvtState } from 'features/dvt/shared'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { OptionCard, TypeBadge } from './styles'; + +const renderStatusChip = ( + typeStatus: DvtTypeStatus, + status: DvtFormStatus | undefined, +) => { + if (typeStatus === 'CLAIMED') { + return Claimed; + } + if (typeStatus === 'ISSUED') { + return Issued; + } + switch (status) { + case 'APPROVED': + return Approved; + case 'REJECTED': + return Rejected; + case 'REVIEW': + return Pending; + default: + return null; + } +}; + +export const IdvtcTypeCard: FC = () => { + const { typeStatus, data } = useDvtState(); + const chip = renderStatusChip(typeStatus, data?.status); + + return ( + + + + IDVTC + {chip} + + + + Identified DVT Cluster + + + Unlock a more resilient and capital-efficient validation path by + creating a verified DVT cluster of independent Community Stakers. + Approval requires meeting criteria and completing verification. + + + + + + ); +}; diff --git a/features/operator-type/index.ts b/features/operator-type/index.ts new file mode 100644 index 000000000..c2b20473b --- /dev/null +++ b/features/operator-type/index.ts @@ -0,0 +1 @@ +export * from './operator-type-page'; diff --git a/features/operator-type/operator-type-page.tsx b/features/operator-type/operator-type-page.tsx new file mode 100644 index 000000000..43ff923c4 --- /dev/null +++ b/features/operator-type/operator-type-page.tsx @@ -0,0 +1,10 @@ +import { FC } from 'react'; + +import { Layout } from 'shared/layout'; +import { TypeOptions } from './type-options'; + +export const OperatorTypePage: FC = () => ( + + + +); diff --git a/features/operator-type/styles.ts b/features/operator-type/styles.ts new file mode 100644 index 000000000..448f15785 --- /dev/null +++ b/features/operator-type/styles.ts @@ -0,0 +1,28 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Block } from '@lidofinance/lido-ui'; +import { CURVE_VARIANTS } from 'shared/node-operator/curve-badge/styles'; +import { BadgeStyle } from 'shared/node-operator/role-badge/styles'; +import styled from 'styled-components'; + +export const OptionsWrap = styled.div` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spaceMap.md}px; +`; + +export const OptionCard = styled(Block)` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spaceMap.xxl}px; +`; + +export const TypeBadge = styled(BadgeStyle)<{ $variant: 'ICS' | 'IDVTC' }>` + font-weight: 700; + color: var(--lido-color-foreground); + padding-inline: 6px; + + ${({ $variant }) => + $variant === 'ICS' + ? CURVE_VARIANTS[OPERATOR_TYPE.CSM_ICS] + : CURVE_VARIANTS[OPERATOR_TYPE.CSM_IDVTC]} +`; diff --git a/features/operator-type/type-options.tsx b/features/operator-type/type-options.tsx new file mode 100644 index 000000000..8fc0ef3fc --- /dev/null +++ b/features/operator-type/type-options.tsx @@ -0,0 +1,17 @@ +import { DvtProviders } from 'features/dvt/shared'; +import { IcsProviders } from 'features/ics/shared'; +import { FC } from 'react'; +import { IcsTypeCard } from './ics-type-card'; +import { IdvtcTypeCard } from './idvtc-type-card'; +import { OptionsWrap } from './styles'; + +export const TypeOptions: FC = () => ( + + + + + + + + +); diff --git a/features/qa-config/index.ts b/features/qa-config/index.ts new file mode 100644 index 000000000..05b4c6a7e --- /dev/null +++ b/features/qa-config/index.ts @@ -0,0 +1 @@ +export * from './qa-config-page'; diff --git a/features/qa-config/qa-config-form.tsx b/features/qa-config/qa-config-form.tsx new file mode 100644 index 000000000..fab81676d --- /dev/null +++ b/features/qa-config/qa-config-form.tsx @@ -0,0 +1,201 @@ +import { Fragment, useCallback, useMemo } from 'react'; +import { useForm } from 'react-hook-form'; + +import { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; +import { Block, Button, Input, ToastSuccess } from '@lidofinance/lido-ui'; + +import { useUserConfig } from 'config/user-config'; +import { CHAIN_METADATA } from 'consts/chains'; +import { FormBlock, Stack } from 'shared/components'; +import { isUrl } from 'utils/is-url'; + +import { Description } from './styles'; + +type FormValues = Record; + +type ChainRow = { + chainId: SUPPORTED_CHAINS; + name: string; + withCl: boolean; +}; + +const rpcKey = (chainId: SUPPORTED_CHAINS) => `rpc_${chainId}`; +const clKey = (chainId: SUPPORTED_CHAINS) => `cl_${chainId}`; +const IPFS_GATEWAYS_KEY = 'ipfsGateways'; +const SURVEY_API_URL_KEY = 'surveyApiUrl'; + +const validateUrl = (value: string) => + !value || isUrl(value) || 'Not a valid URL'; + +const parseGateways = (value: string): string[] => + value + .split(',') + .map((url) => url.trim()) + .filter(Boolean); + +const validateGateways = (value: string) => { + const invalid = parseGateways(value).find((url) => !isUrl(url)); + return !invalid || `Not a valid URL: ${invalid}`; +}; + +export const QaConfigForm = () => { + const { + savedUserConfig, + setSavedUserConfig, + resetSavedUserConfig, + defaultChain, + } = useUserConfig(); + + const rows = useMemo(() => { + const list: ChainRow[] = [ + { + chainId: CHAINS.Mainnet, + name: CHAIN_METADATA[CHAINS.Mainnet].name, + withCl: defaultChain === CHAINS.Mainnet, + }, + ]; + if (defaultChain !== CHAINS.Mainnet) { + list.push({ + chainId: defaultChain, + name: CHAIN_METADATA[defaultChain].name, + withCl: true, + }); + } + return list; + }, [defaultChain]); + + const defaultValues = useMemo(() => { + const values: FormValues = {}; + for (const { chainId, withCl } of rows) { + values[rpcKey(chainId)] = savedUserConfig.rpcUrls[chainId] ?? ''; + if (withCl) { + values[clKey(chainId)] = savedUserConfig.clApiUrls[chainId] ?? ''; + } + } + values[IPFS_GATEWAYS_KEY] = savedUserConfig.ipfsGateways.join(', '); + values[SURVEY_API_URL_KEY] = savedUserConfig.surveyApiUrl ?? ''; + return values; + }, [rows, savedUserConfig]); + + const { register, handleSubmit, reset, formState } = useForm({ + mode: 'onChange', + defaultValues, + }); + + const save = useCallback( + (values: FormValues) => { + const rpcUrls: Partial> = {}; + const clApiUrls: Partial> = {}; + + for (const { chainId, withCl } of rows) { + const rpc = values[rpcKey(chainId)]?.trim(); + if (rpc) rpcUrls[chainId] = rpc; + if (withCl) { + const cl = values[clKey(chainId)]?.trim(); + if (cl) clApiUrls[chainId] = cl; + } + } + + const ipfsGateways = parseGateways(values[IPFS_GATEWAYS_KEY] ?? ''); + const surveyApiUrl = values[SURVEY_API_URL_KEY]?.trim() || undefined; + + setSavedUserConfig({ rpcUrls, clApiUrls, ipfsGateways, surveyApiUrl }); + ToastSuccess('QA endpoints saved. Reload the page to apply.'); + }, + [rows, setSavedUserConfig], + ); + + const handleReset = useCallback(() => { + resetSavedUserConfig(); + + const empty: FormValues = {}; + for (const key of Object.keys(defaultValues)) empty[key] = ''; + reset(empty); + + ToastSuccess('QA endpoints reset to defaults'); + }, [defaultValues, reset, resetSavedUserConfig]); + + return ( + <> + +
          + {rows.map(({ chainId, name, withCl }) => ( + + + {withCl && ( + + )} + + ))} + + + + + + +
          +
          + + + +

          + Override the JSON-RPC endpoint, Consensus Layer API base URL, IPFS + gateway, and Surveys API base URL used by the widget. Intended for + QA against custom forks or staging backends — not for end users. +

          +

          + The IPFS gateway is tried before the default public gateways and may + include a {'{cid}'} placeholder; otherwise the CID is + appended to the URL +

          +

          + Values are stored in localStorage under{' '} + lido-user-config and persist across reloads. Leave a + field empty to fall back to the default backend proxy. +

          +

          + Reload the page after saving for the new endpoints + to be picked up everywhere +

          +
          +
          + + ); +}; diff --git a/features/qa-config/qa-config-page.tsx b/features/qa-config/qa-config-page.tsx new file mode 100644 index 000000000..3df5fb1b5 --- /dev/null +++ b/features/qa-config/qa-config-page.tsx @@ -0,0 +1,17 @@ +import { FC } from 'react'; + +import { Layout } from 'shared/layout'; +import { QaConfigForm } from './qa-config-form'; +import { QaFeatureFlags } from './qa-feature-flags'; + +export const QaConfigPage: FC = () => ( + + + + +); diff --git a/features/qa-config/qa-feature-flags.tsx b/features/qa-config/qa-feature-flags.tsx new file mode 100644 index 000000000..d22b0321f --- /dev/null +++ b/features/qa-config/qa-feature-flags.tsx @@ -0,0 +1,65 @@ +import { FC, useMemo } from 'react'; + +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; +import { Checkbox, Text } from '@lidofinance/lido-ui'; + +import { + DISABLE_DEPOSIT_DATA_VALIDATION, + FeatureFlagsType, + getFeatureFlagsDefault, + ICS_APPLY_FORM, + SURVEYS_SETUP_ENABLED, + useFeatureFlags, +} from 'config/feature-flags'; +import { useUserConfig } from 'config/user-config'; +import { FormBlock, Stack } from 'shared/components'; + +const FLAG_LABELS: Record = { + [ICS_APPLY_FORM]: 'Operator type applications (ICS, IDVTC)', + [SURVEYS_SETUP_ENABLED]: 'Surveys (setup & delegation)', + [DISABLE_DEPOSIT_DATA_VALIDATION]: 'Disable deposit data validation', +}; + +const FLAGS = Object.keys(getFeatureFlagsDefault()) as Array< + keyof FeatureFlagsType +>; + +const TESTNET_ONLY_FLAGS: Array = [ + ICS_APPLY_FORM, + SURVEYS_SETUP_ENABLED, +]; + +export const QaFeatureFlags: FC = () => { + const featureFlags = useFeatureFlags(); + const { defaultChain } = useUserConfig(); + + const flags = useMemo( + () => + defaultChain === CHAINS.Mainnet + ? FLAGS.filter((flag) => !TESTNET_ONLY_FLAGS.includes(flag)) + : FLAGS, + [defaultChain], + ); + + if (!featureFlags) return null; + + return ( + + + Feature flags + + + {flags.map((flag) => ( + + featureFlags.setFeatureFlag(flag, e.currentTarget.checked) + } + /> + ))} + + + ); +}; diff --git a/features/qa-config/styles.ts b/features/qa-config/styles.ts new file mode 100644 index 000000000..51224f219 --- /dev/null +++ b/features/qa-config/styles.ts @@ -0,0 +1,14 @@ +import { Stack } from 'shared/components'; +import styled from 'styled-components'; + +export const Description = styled(Stack).attrs({ + direction: 'column', + gap: 'sm', +})` + & code { + padding: 1px 4px; + background: var(--lido-color-backgroundSecondary); + border-radius: 3px; + font-size: 0.9em; + } +`; diff --git a/features/remove-keys/remove-keys-page.tsx b/features/remove-keys/remove-keys-page.tsx index 3d6a600b0..98b3f7ed0 100644 --- a/features/remove-keys/remove-keys-page.tsx +++ b/features/remove-keys/remove-keys-page.tsx @@ -1,17 +1,26 @@ import { FC } from 'react'; import { Layout } from 'shared/layout'; -import { KeysPageSwitcher } from 'shared/navigate'; +import { + DeleteKeysSwitcher, + DeleteKeysSwitcherRoutes, + KeysPageSwitcher, +} from 'shared/navigate'; import { RemoveKeys } from './remove-keys'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { Faq, FormBlock } from 'shared/components'; +import { FAQ_KEYS } from 'faq'; export const RemoveKeysPage: FC = () => ( - + + + + + ); diff --git a/features/remove-keys/remove-keys.tsx b/features/remove-keys/remove-keys.tsx index 1211c6a2c..e5912a058 100644 --- a/features/remove-keys/remove-keys.tsx +++ b/features/remove-keys/remove-keys.tsx @@ -1,7 +1,6 @@ import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; +import { useWeb3Key } from 'shared/hooks'; import { RemoveKeysForm } from './remove-keys/remove-keys-form'; -import { Faq } from 'shared/components'; export const RemoveKeys = () => { const key = useWeb3Key(); @@ -10,7 +9,6 @@ export const RemoveKeys = () => { - ); }; diff --git a/features/remove-keys/remove-keys/context/index.ts b/features/remove-keys/remove-keys/context/index.ts index 8bab41492..8dcf06f8f 100644 --- a/features/remove-keys/remove-keys/context/index.ts +++ b/features/remove-keys/remove-keys/context/index.ts @@ -1,5 +1,4 @@ -export { - RemoveKeysFormProvider, - useRemoveKeysFormData, -} from './remove-keys-form-provider'; +export * from './remove-keys-data-provider'; +export * from './remove-keys-form-provider'; export * from './types'; +export * from './use-remove-keys-flow'; diff --git a/features/remove-keys/remove-keys/context/remove-keys-data-provider.tsx b/features/remove-keys/remove-keys/context/remove-keys-data-provider.tsx new file mode 100644 index 000000000..8dfb8f879 --- /dev/null +++ b/features/remove-keys/remove-keys/context/remove-keys-data-provider.tsx @@ -0,0 +1,97 @@ +import { KEY_STATUS } from '@lidofinance/lido-csm-sdk'; +import { + KEY_DEPOSIT_QUEUE_BATCHES, + KEY_OPERATOR_BALANCE, + KEY_OPERATOR_INFO, + KEY_OPERATOR_KEYS, + useKeyRemovalFee, + useNodeOperatorId, + useOperatorBalance, + useOperatorCurveId, + useOperatorInfo, + useOperatorKeysWithStatus, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import { hasStatus } from 'utils'; +import { type RemoveKeysFormNetworkData } from './types'; + +const useRemoveKeysFormNetworkData: NetworkData< + RemoveKeysFormNetworkData +> = () => { + const nodeOperatorId = useNodeOperatorId(); + const bondQuery = useOperatorBalance(nodeOperatorId); + const infoQuery = useOperatorInfo(nodeOperatorId); + const keysQuery = useOperatorKeysWithStatus(nodeOperatorId, (keys) => + keys.filter( + hasStatus([ + KEY_STATUS.DEPOSITABLE, + KEY_STATUS.NON_QUEUED, + KEY_STATUS.UNCHECKED, + KEY_STATUS.DUPLICATED, // TODO: check active duplicated key is here? + KEY_STATUS.INVALID, + ]), + ), + ); + + const bond = bondQuery.data; + const info = infoQuery.data; + const keys = keysQuery.data; + + const isBondLoading = bondQuery.isPending; + const isInfoLoading = infoQuery.isPending; + const isKeysLoading = keysQuery.isPending; + + const { data: curveId, isPending: isCurveIdLoading } = + useOperatorCurveId(nodeOperatorId); + const { data: removalFee, isPending: isRemovalFeeLoading } = + useKeyRemovalFee(curveId); + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ + KEY_OPERATOR_BALANCE, + KEY_OPERATOR_INFO, + KEY_OPERATOR_KEYS, + KEY_DEPOSIT_QUEUE_BATCHES, + ]); + }, [invalidate]); + + const isPending = + isBondLoading || + isInfoLoading || + isCurveIdLoading || + isRemovalFeeLoading || + isKeysLoading; + + return { + data: { + nodeOperatorId, + curveId, + removalFee, + bond, + keys, + info, + } as RemoveKeysFormNetworkData, + isPending, + revalidate, + }; +}; + +export const useRemoveKeysFormData = useFormData; + +export const RemoveKeysDataProvider: FC = ({ children }) => { + const networkData = useRemoveKeysFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/remove-keys/remove-keys/context/remove-keys-form-provider.tsx b/features/remove-keys/remove-keys/context/remove-keys-form-provider.tsx index 48bee78cd..0adfb7945 100644 --- a/features/remove-keys/remove-keys/context/remove-keys-form-provider.tsx +++ b/features/remove-keys/remove-keys/context/remove-keys-form-provider.tsx @@ -1,60 +1,34 @@ -import { FC, PropsWithChildren, useMemo } from 'react'; +import { FC, PropsWithChildren } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormData, + FormControllerProvider, + useFlowSubmit, + useFormDefaultValues, } from 'shared/hook-form/form-controller'; -import { useFormControllerRetry } from 'shared/hook-form/form-controller/use-form-controller-retry-delegate'; -import { - RemoveKeysFormNetworkData, - type RemoveKeysFormInputType, -} from './types'; -import { useGetDefaultValues } from './use-get-default-values'; -import { useRemoveKeysFormNetworkData } from './use-remove-keys-form-network-data'; -import { useRemoveKeysSubmit } from './use-remove-keys-submit'; +import { type RemoveKeysFormInputType } from './types'; +import { useRemoveKeysFlowResolver } from './use-remove-keys-flow'; import { useRemoveKeysValidation } from './use-remove-keys-validation'; -export const useRemoveKeysFormData = useFormData; - export const RemoveKeysFormProvider: FC = ({ children }) => { - const [networkData, revalidate] = useRemoveKeysFormNetworkData(); - const validationResolver = useRemoveKeysValidation(); + const resolver = useRemoveKeysValidation(); - const asyncDefaultValues = useGetDefaultValues(networkData); + const defaultValues = useFormDefaultValues(() => ({ + selection: { start: 0, count: 0 }, + })); const formObject = useForm({ - defaultValues: asyncDefaultValues, - resolver: validationResolver, + defaultValues, + resolver, mode: 'onChange', }); - const { retryEvent, retryFire } = useFormControllerRetry(); - - const removeKeys = useRemoveKeysSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - RemoveKeysFormInputType, - RemoveKeysFormNetworkData - > = useMemo( - () => ({ - onSubmit: removeKeys, - retryEvent, - }), - [removeKeys, retryEvent], - ); + const submitter = useFlowSubmit(useRemoveKeysFlowResolver()); return ( - - - {children} - - + + {children} + ); }; diff --git a/features/remove-keys/remove-keys/context/types.ts b/features/remove-keys/remove-keys/context/types.ts index ebedc6afa..ccf6d3d22 100644 --- a/features/remove-keys/remove-keys/context/types.ts +++ b/features/remove-keys/remove-keys/context/types.ts @@ -1,5 +1,5 @@ -import { KeyWithStatus, useNodeOperatorInfo } from 'shared/hooks'; -import { BondBalance, LoadingRecord, NodeOperatorId } from 'types'; +import { KeyWithStatus, NodeOperatorInfo } from '@lidofinance/lido-csm-sdk'; +import { BondBalance, NodeOperatorId } from '@lidofinance/lido-csm-sdk'; export type RemoveKeysFormInputType = { selection: { @@ -9,9 +9,10 @@ export type RemoveKeysFormInputType = { }; export type RemoveKeysFormNetworkData = { - nodeOperatorId?: NodeOperatorId; - keys?: KeyWithStatus[]; - info?: ReturnType['data']; - bond?: BondBalance; - loading: LoadingRecord<'keys' | 'bond' | 'info'>; + nodeOperatorId: NodeOperatorId; + curveId: bigint; + keys: KeyWithStatus[]; + info: NodeOperatorInfo; + bond: BondBalance; + removalFee: bigint; }; diff --git a/features/remove-keys/remove-keys/context/use-get-default-values.tsx b/features/remove-keys/remove-keys/context/use-get-default-values.tsx deleted file mode 100644 index b498a5137..000000000 --- a/features/remove-keys/remove-keys/context/use-get-default-values.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { useCallback, useMemo } from 'react'; -import { useAwaiter } from 'shared/hooks'; -import { RemoveKeysFormNetworkData } from './types'; - -// TODO: select invalid key -export const useGetDefaultValues = ({ - loading: { isKeysLoading, isInfoLoading }, -}: RemoveKeysFormNetworkData) => { - const values = useMemo(() => { - if (isKeysLoading || isInfoLoading) return undefined; - return { - selection: { - start: 0, - count: 0, - }, - }; - }, [isInfoLoading, isKeysLoading]); - - const { awaiter } = useAwaiter(values); - - return useCallback(() => awaiter, [awaiter]); -}; diff --git a/features/remove-keys/remove-keys/context/use-remove-keys-flow.ts b/features/remove-keys/remove-keys/context/use-remove-keys-flow.ts new file mode 100644 index 000000000..c7392886c --- /dev/null +++ b/features/remove-keys/remove-keys/context/use-remove-keys-flow.ts @@ -0,0 +1,58 @@ +import { type MethodAccess } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useCanPerform } from 'shared/hooks'; +import { useTxModalStagesRemoveKeys } from '../hooks/use-tx-modal-stages-remove-keys'; +import { useRemoveKeysFormData } from './remove-keys-data-provider'; +import { RemoveKeysFormInputType, RemoveKeysFormNetworkData } from './types'; + +export type RemoveKeysFlow = + | { action: 'no-access'; access: MethodAccess } + | { action: 'no-keys' } + | ({ action: 'remove' } & Executable); + +export const useRemoveKeysFlowResolver = (): FlowResolver< + RemoveKeysFormInputType, + RemoveKeysFormNetworkData, + RemoveKeysFlow +> => { + const { keys: keysSDK } = useSmSDK(); + const [canRemoveKeys, access] = useCanPerform(keysSDK, 'removeKeys'); + const buildCallback = useTxModalStagesRemoveKeys(); + + return useCallback( + (input, data) => { + if (!canRemoveKeys) return { action: 'no-access', access }; + if (!data.keys?.length) return { action: 'no-keys' }; + + return { + action: 'remove' as const, + submit: async () => { + const { start, count } = input.selection; + const pubkeys = data.keys + .map(({ pubkey }) => pubkey) + .slice(start, start + count); + + return keysSDK.removeKeys({ + nodeOperatorId: data.nodeOperatorId, + startIndex: BigInt(data.info.totalDepositedKeys + start), + keysCount: BigInt(count), + pubkeys, + callback: buildCallback(input, data), + }); + }, + }; + }, + [canRemoveKeys, access, keysSDK, buildCallback], + ); +}; + +export const useRemoveKeysFlow = (): RemoveKeysFlow => { + const resolve = useRemoveKeysFlowResolver(); + const data = useRemoveKeysFormData(true); + return resolve({} as RemoveKeysFormInputType, data); +}; diff --git a/features/remove-keys/remove-keys/context/use-remove-keys-form-network-data.tsx b/features/remove-keys/remove-keys/context/use-remove-keys-form-network-data.tsx deleted file mode 100644 index bfd4e1f5c..000000000 --- a/features/remove-keys/remove-keys/context/use-remove-keys-form-network-data.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { useCallback, useMemo } from 'react'; -import { - useKeysWithStatus, - useNodeOperatorBalance, - useNodeOperatorInfo, -} from 'shared/hooks'; -import { type RemoveKeysFormNetworkData } from './types'; - -export const useRemoveKeysFormNetworkData = (): [ - RemoveKeysFormNetworkData, - () => Promise, -] => { - const nodeOperatorId = useNodeOperatorId(); - const { - data: bond, - update: updateBond, - initialLoading: isBondLoading, - } = useNodeOperatorBalance(nodeOperatorId); - const { - data: info, - update: updateInfo, - initialLoading: isInfoLoading, - } = useNodeOperatorInfo(nodeOperatorId); - - const { - data: keys, - update: updateKeys, - initialLoading: isKeysLoading, - } = useKeysWithStatus(true); - - const revalidate = useCallback(async () => { - await Promise.allSettled([updateBond(), updateInfo(), updateKeys()]); - }, [updateBond, updateInfo, updateKeys]); - - const loading = useMemo( - () => ({ - isBondLoading, - isInfoLoading, - isKeysLoading, - }), - [isBondLoading, isInfoLoading, isKeysLoading], - ); - - return [ - { - nodeOperatorId, - bond, - keys, - info, - loading, - }, - revalidate, - ]; -}; diff --git a/features/remove-keys/remove-keys/context/use-remove-keys-submit.ts b/features/remove-keys/remove-keys/context/use-remove-keys-submit.ts deleted file mode 100644 index 18a10359c..000000000 --- a/features/remove-keys/remove-keys/context/use-remove-keys-submit.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { useCallback } from 'react'; -import { useCSModuleWeb3, useKeysCache } from 'shared/hooks'; -import { useSendTx } from 'shared/hooks/use-send-tx'; -import { handleTxError } from 'shared/transaction-modal'; -import invariant from 'tiny-invariant'; -import { NodeOperatorId } from 'types'; -import { runWithTransactionLogger } from 'utils'; -import { useTxModalStagesRemoveKeys } from '../hooks/use-tx-modal-stages-remove-keys'; -import { RemoveKeysFormInputType, RemoveKeysFormNetworkData } from './types'; - -type RemoveKeysOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type MethodParams = { - nodeOperatorId: NodeOperatorId; - startIndex: number; - keysCount: number; -}; - -// this encapsulates eth/steth/wsteth flows -const useRemoveKeysTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async (params: MethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - return { - tx: await CSModuleWeb3.populateTransaction.removeKeys( - params.nodeOperatorId, - params.startIndex, - params.keysCount, - ), - txName: 'removeKeys', - }; - }, - [CSModuleWeb3], - ); -}; - -export const useRemoveKeysSubmit = ({ - onConfirm, - onRetry, -}: RemoveKeysOptions) => { - const { txModalStages } = useTxModalStagesRemoveKeys(); - const getTx = useRemoveKeysTx(); - const sendTx = useSendTx(); - const { removeCacheKeys } = useKeysCache(); - - return useCallback( - async ( - { selection: { start, count } }: RemoveKeysFormInputType, - { nodeOperatorId, info, keys }: RemoveKeysFormNetworkData, - ): Promise => { - invariant(nodeOperatorId, 'NodeOperatorId is not defined'); - invariant(keys, 'Keys are not defined'); - invariant( - info?.totalDepositedKeys !== undefined, - 'Offset is not defined', - ); - - const startIndex = info.totalDepositedKeys + start; - const keysCount = count; - - try { - txModalStages.sign({ keysCount }); - - const tx = await getTx({ - startIndex, - keysCount, - nodeOperatorId, - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'RemoveKeys signing', - () => sendTx(tx), - ); - - txModalStages.pending({ keysCount }, txHash); - - await runWithTransactionLogger('RemoveKeys block confirmation', waitTx); - - await onConfirm?.(); - - txModalStages.success({ keysCount }, txHash); - - void removeCacheKeys( - keys.map(({ key }) => key).slice(start, start + count), - ); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [txModalStages, getTx, onConfirm, removeCacheKeys, sendTx, onRetry], - ); -}; diff --git a/features/remove-keys/remove-keys/context/use-remove-keys-validation.ts b/features/remove-keys/remove-keys/context/use-remove-keys-validation.ts index beb0b3860..5bba6ef13 100644 --- a/features/remove-keys/remove-keys/context/use-remove-keys-validation.ts +++ b/features/remove-keys/remove-keys/context/use-remove-keys-validation.ts @@ -1,30 +1,21 @@ -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; import { - handleResolverValidationError, + useFormValidation, ValidationError, } from 'shared/hook-form/validation'; -import type { RemoveKeysFormInputType } from './types'; +import type { + RemoveKeysFormInputType, + RemoveKeysFormNetworkData, +} from './types'; export const useRemoveKeysValidation = () => { - return useCallback>(async (values) => { - try { - const { selection } = values; - - if (selection.count === 0) { - throw new ValidationError('selection', 'No keys selected'); - } - - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError( - error, - 'RemoveKeysForm', - 'selection', - ); - } - }, []); + return useFormValidation( + 'selection', + async ({ selection }, _, validate) => { + await validate('selection', () => { + if (selection.count === 0) { + throw new ValidationError('selection', 'No keys selected'); + } + }); + }, + ); }; diff --git a/features/remove-keys/remove-keys/controls/amount-input.tsx b/features/remove-keys/remove-keys/controls/amount-input.tsx new file mode 100644 index 000000000..f825442c6 --- /dev/null +++ b/features/remove-keys/remove-keys/controls/amount-input.tsx @@ -0,0 +1,31 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { DisabledInputAmount, Stack } from 'shared/components'; +import { RemoveKeysFormInputType, useRemoveKeysFormData } from '../context'; +import { useWatch } from 'react-hook-form'; + +export const AmountInput = () => { + const { removalFee } = useRemoveKeysFormData(true); + + const { count } = useWatch({ + name: 'selection', + }); + + if (!removalFee) return null; + + return ( + + + + Will be deducted from your bond balance + + + ); +}; diff --git a/features/remove-keys/remove-keys/controls/keys-selector.tsx b/features/remove-keys/remove-keys/controls/keys-selector.tsx index 4c8447b75..aaf0af244 100644 --- a/features/remove-keys/remove-keys/controls/keys-selector.tsx +++ b/features/remove-keys/remove-keys/controls/keys-selector.tsx @@ -1,15 +1,17 @@ import { FormTitle, Note } from 'shared/components'; +import { RemoveKeysSelectorHookForm } from 'shared/hook-form/controls'; import { useRemoveKeysFormData } from '../context'; -import { KeysSelectorHookForm } from 'shared/hook-form/controls'; export const KeysSelector = () => { - const { keys } = useRemoveKeysFormData(); + const { keys } = useRemoveKeysFormData(true); return ( <> Choose keys to remove - - Your choice has to be a sequential array + + {keys && keys?.length > 2 && ( + Your choice has to be a sequential array + )} ); }; diff --git a/features/remove-keys/remove-keys/controls/submit-button.tsx b/features/remove-keys/remove-keys/controls/submit-button.tsx index b8d6fa15d..7607d34a8 100644 --- a/features/remove-keys/remove-keys/controls/submit-button.tsx +++ b/features/remove-keys/remove-keys/controls/submit-button.tsx @@ -1,9 +1,5 @@ import { SubmitButtonHookForm } from 'shared/hook-form/controls'; export const SubmitButton = () => { - return ( - - Remove Keys - - ); + return Remove Keys; }; diff --git a/features/remove-keys/remove-keys/form-loading.tsx b/features/remove-keys/remove-keys/form-loading.tsx deleted file mode 100644 index 6373cca72..000000000 --- a/features/remove-keys/remove-keys/form-loading.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { FC, PropsWithChildren } from 'react'; -import { useFormState } from 'react-hook-form'; -import { WhenLoaded } from 'shared/components'; -import { RemoveKeysFormInputType, useRemoveKeysFormData } from './context'; - -export const FormLoading: FC = ({ children }) => { - const { isLoading } = useFormState(); - const { loading, keys } = useRemoveKeysFormData(); - const isEmpty = !keys?.length; - - return ( - No keys available to remove} - emptyNote="Only keys that have not been deposited yet can be deleted. If a key has already been deposited, the only way to retrieve the bond is to exit the validator on the Consensus Layer (CL)." - > - {children} - - ); -}; diff --git a/features/remove-keys/remove-keys/hooks/use-bond-balance-after-remove-keys.ts b/features/remove-keys/remove-keys/hooks/use-bond-balance-after-remove-keys.ts new file mode 100644 index 000000000..f5abaeb82 --- /dev/null +++ b/features/remove-keys/remove-keys/hooks/use-bond-balance-after-remove-keys.ts @@ -0,0 +1,36 @@ +import { useQuery } from '@tanstack/react-query'; +import { useBondByKeysCount } from 'modules/web3'; +import invariant from 'tiny-invariant'; +import { useRemoveKeysFormData } from '../context'; +import { calcBondBalance } from '@lidofinance/lido-csm-sdk'; + +export const useBondBalanceAfterRemoveKeys = (count = 0) => { + const { info, bond, removalFee, curveId } = useRemoveKeysFormData(true); + + const nextKeysCount = info.totalAddedKeys - info.totalWithdrawnKeys - count; + + const { data: bondRequiredAfter } = useBondByKeysCount({ + keysCount: nextKeysCount, + curveId, + }); + + const bondAfter = bond.current - removalFee * BigInt(count); + + return useQuery({ + queryKey: [ + 'getBondBalanceAfterRemoveKeys', + { bondRequiredAfter, bondAfter }, + ], + queryFn: () => { + invariant(bondRequiredAfter !== undefined); + return calcBondBalance({ + current: bondAfter, + required: bondRequiredAfter, + locked: 0n, + debt: bond.debt, + pendingToSplit: bond.pendingToSplit, + }); + }, + enabled: bondRequiredAfter !== undefined, + }); +}; diff --git a/features/remove-keys/remove-keys/hooks/use-tx-modal-stages-remove-keys.tsx b/features/remove-keys/remove-keys/hooks/use-tx-modal-stages-remove-keys.tsx index c0c63a54c..8820e2681 100644 --- a/features/remove-keys/remove-keys/hooks/use-tx-modal-stages-remove-keys.tsx +++ b/features/remove-keys/remove-keys/hooks/use-tx-modal-stages-remove-keys.tsx @@ -1,58 +1,49 @@ import { Plural } from 'shared/components'; import { - TransactionModalTransitStage, TxStagePending, TxStageSign, TxStageSuccess, - getGeneralTransactionModalStages, - useTransactionModalStage, + useTxStages, } from 'shared/transaction-modal'; +import { + RemoveKeysFormInputType, + RemoveKeysFormNetworkData, +} from '../context/types'; -type Props = { - keysCount: number; -}; - -const getTxModalStagesRemoveKeys = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: (props: Props) => - transitStage( - , - ), - - pending: (props: Props, txHash?: string) => - transitStage( - , - ), - - success: (props: Props, txHash?: string) => - transitStage( - - {props.keysCount}{' '} - has - been removed - - } - description="" - />, - { - isClosableOnLedger: true, - }, - ), -}); - -export const useTxModalStagesRemoveKeys = () => { - return useTransactionModalStage(getTxModalStagesRemoveKeys); -}; +export const useTxModalStagesRemoveKeys = () => + useTxStages( + (transitStage, input) => ({ + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (_result: undefined, txHash) => + transitStage( + + {input.selection.count}{' '} + {' '} + removed + + } + description="" + />, + ), + }), + ); diff --git a/features/remove-keys/remove-keys/hooks/useBondBalanceAfterRemoveKeys.ts b/features/remove-keys/remove-keys/hooks/useBondBalanceAfterRemoveKeys.ts deleted file mode 100644 index 222dfced7..000000000 --- a/features/remove-keys/remove-keys/hooks/useBondBalanceAfterRemoveKeys.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { useMemo } from 'react'; -import { - useExtendedBondBalance, - useMergeSwr, - useNodeOperatorCurveId, - useNodeOperatorFirstKeysBond, -} from 'shared/hooks'; -import { NodeOperatorId } from 'types'; -import { useRemoveKeysFormData } from '../context'; -import { useRemovalFeeByKeysCount } from './useRemovalFeeByKeysCount'; - -export const useBondBalanceAfterRemoveKeys = ( - nodeOperatorId?: NodeOperatorId, - count = 0, -) => { - const { info, bond } = useRemoveKeysFormData(); - - const nextKeysCount = useMemo(() => { - return info - ? info.totalAddedKeys - info.totalWithdrawnKeys - count - : undefined; - }, [count, info]); - - const swrCurveId = useNodeOperatorCurveId(nodeOperatorId); - const swrRequiredAfter = useNodeOperatorFirstKeysBond({ - keysCount: nextKeysCount, - curveId: swrCurveId.data, - }); - - const swrRemovalFee = useRemovalFeeByKeysCount(count); - const bondAfter = useMemo( - () => bond?.current.sub(swrRemovalFee.data || 0), - [bond, swrRemovalFee.data], - ); - const bondBalance = useExtendedBondBalance(swrRequiredAfter.data, bondAfter); - - return useMergeSwr( - [swrCurveId, swrRequiredAfter, swrRemovalFee], - bondBalance, - ); -}; diff --git a/features/remove-keys/remove-keys/hooks/useRemovalFeeByKeysCount.ts b/features/remove-keys/remove-keys/hooks/useRemovalFeeByKeysCount.ts deleted file mode 100644 index 8b74ff035..000000000 --- a/features/remove-keys/remove-keys/hooks/useRemovalFeeByKeysCount.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useCsmKeyRemovalFee, useMergeSwr } from 'shared/hooks'; -import { useMemo } from 'react'; - -export const useRemovalFeeByKeysCount = (count: number) => { - const swr = useCsmKeyRemovalFee(); - const data = useMemo(() => swr.data?.mul(count), [count, swr.data]); - - return useMergeSwr([swr], data); -}; diff --git a/features/remove-keys/remove-keys/remove-keys-form-info.tsx b/features/remove-keys/remove-keys/remove-keys-form-info.tsx index dd8edf9f7..9f33deff3 100644 --- a/features/remove-keys/remove-keys/remove-keys-form-info.tsx +++ b/features/remove-keys/remove-keys/remove-keys-form-info.tsx @@ -1,38 +1,32 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; import { DataTable, DataTableRow } from '@lidofinance/lido-ui'; -import { TOKENS } from 'consts/tokens'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; import { useWatch } from 'react-hook-form'; import { FormatToken } from 'shared/formatters'; import { RemoveKeysFormInputType } from './context'; -import { useBondBalanceAfterRemoveKeys } from './hooks/useBondBalanceAfterRemoveKeys'; -import { useRemovalFeeByKeysCount } from './hooks/useRemovalFeeByKeysCount'; +import { useBondBalanceAfterRemoveKeys } from './hooks/use-bond-balance-after-remove-keys'; export const RemoveKeysFormInfo = () => { const { count } = useWatch({ name: 'selection', }); - const nodeOperatorId = useNodeOperatorId(); - const { data: removalFee, initialLoading: isRemovalFeeLoading } = - useRemovalFeeByKeysCount(count); - const { data: balance, initialLoading: isBalanceLoading } = - useBondBalanceAfterRemoveKeys(nodeOperatorId, count); + const { data: balance, isPending: isBalanceLoading } = + useBondBalanceAfterRemoveKeys(count); return ( - {count} - + {count} - + ); diff --git a/features/remove-keys/remove-keys/remove-keys-form-loader.tsx b/features/remove-keys/remove-keys/remove-keys-form-loader.tsx new file mode 100644 index 000000000..2e2cd4ddd --- /dev/null +++ b/features/remove-keys/remove-keys/remove-keys-form-loader.tsx @@ -0,0 +1,28 @@ +import { FC, PropsWithChildren } from 'react'; +import { EmptyState, NoAccessNotice } from 'shared/components'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useRemoveKeysFlow } from './context'; + +const RemoveKeysFormGate: FC = ({ children }) => { + const flow = useRemoveKeysFlow(); + + if (flow.action === 'no-access') { + return ; + } + + if (flow.action === 'no-keys') { + return ( + + No keys available to remove + + ); + } + + return <>{children}; +}; + +export const RemoveKeysFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/remove-keys/remove-keys/remove-keys-form.tsx b/features/remove-keys/remove-keys/remove-keys-form.tsx index 80ca4df3a..36b429087 100644 --- a/features/remove-keys/remove-keys/remove-keys-form.tsx +++ b/features/remove-keys/remove-keys/remove-keys-form.tsx @@ -1,24 +1,28 @@ import { FC, memo } from 'react'; -import { RemoveKeysFormProvider } from './context'; +import { FormBlock } from 'shared/components'; +import { Form } from 'shared/hook-form/form-controller'; +import { RemoveKeysDataProvider, RemoveKeysFormProvider } from './context'; +import { AmountInput } from './controls/amount-input'; import { KeysSelector } from './controls/keys-selector'; import { SubmitButton } from './controls/submit-button'; -import { FormLoading } from './form-loading'; import { RemoveKeysFormInfo } from './remove-keys-form-info'; -import { FormBlock } from 'shared/components'; -import { FormControllerStyled } from 'shared/hook-form/form-controller'; +import { RemoveKeysFormLoader } from './remove-keys-form-loader'; export const RemoveKeysForm: FC = memo(() => { return ( - - - - - - - - - - - + + + + +
          + + + + + +
          +
          +
          +
          ); }); diff --git a/features/rewards-history/index.ts b/features/rewards-history/index.ts new file mode 100644 index 000000000..cf74749b8 --- /dev/null +++ b/features/rewards-history/index.ts @@ -0,0 +1,2 @@ +export * from './rewards-history-page'; +export * from './rewards-history'; diff --git a/features/rewards-history/rewards-history-page.tsx b/features/rewards-history/rewards-history-page.tsx new file mode 100644 index 000000000..61172ffdc --- /dev/null +++ b/features/rewards-history/rewards-history-page.tsx @@ -0,0 +1,19 @@ +import { FC } from 'react'; + +import { Layout } from 'shared/layout'; +import { BondPageSwitcher } from 'shared/navigate'; +import { RewardsHistory } from './rewards-history'; +import { Faq } from 'shared/components'; +import { FAQ_BOND } from 'faq'; + +export const RewardsHistoryPage: FC = () => ( + + + + + +); diff --git a/features/rewards-history/rewards-history-section/filters-and-export/filters-and-export.tsx b/features/rewards-history/rewards-history-section/filters-and-export/filters-and-export.tsx new file mode 100644 index 000000000..5ca16c8f3 --- /dev/null +++ b/features/rewards-history/rewards-history-section/filters-and-export/filters-and-export.tsx @@ -0,0 +1,31 @@ +import { ButtonIcon } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { FC, useCallback } from 'react'; +import { trackMatomoEvent } from 'utils'; +import { SectionWrapper } from './styles'; +import { useRewardsHistoryExport } from './use-rewards-history-export'; + +import { ReactComponent as DownloadIcon } from 'assets/icons/download.svg'; + +export const FiltersAndExport: FC = () => { + const { exportToCsv, isExporting } = useRewardsHistoryExport(); + + const handleExport = useCallback(() => { + trackMatomoEvent(MATOMO_CLICK_EVENTS_TYPES.rewardsHistoryExport); + void exportToCsv(); + }, [exportToCsv]); + + return ( + + } + size="xs" + variant="outlined" + onClick={handleExport} + loading={isExporting} + > + Export all to CSV + + + ); +}; diff --git a/features/rewards-history/rewards-history-section/filters-and-export/index.ts b/features/rewards-history/rewards-history-section/filters-and-export/index.ts new file mode 100644 index 000000000..039efd179 --- /dev/null +++ b/features/rewards-history/rewards-history-section/filters-and-export/index.ts @@ -0,0 +1 @@ +export * from './filters-and-export'; diff --git a/features/rewards-history/rewards-history-section/filters-and-export/styles.ts b/features/rewards-history/rewards-history-section/filters-and-export/styles.ts new file mode 100644 index 000000000..f6ea9a93a --- /dev/null +++ b/features/rewards-history/rewards-history-section/filters-and-export/styles.ts @@ -0,0 +1,13 @@ +import styled from 'styled-components'; + +export const SectionWrapper = styled.div` + display: flex; + align-items: center; + justify-content: flex-end; + gap: ${({ theme }) => theme.spaceMap.sm}px; + padding: ${({ theme }) => theme.spaceMap.md}px + ${({ theme }) => theme.spaceMap.xxl}px + calc(${({ theme }) => theme.spaceMap.md}px - 1px); + + border-bottom: 1px solid var(--lido-color-border); +`; diff --git a/features/rewards-history/rewards-history-section/filters-and-export/use-rewards-history-export.ts b/features/rewards-history/rewards-history-section/filters-and-export/use-rewards-history-export.ts new file mode 100644 index 000000000..0f2df1ca7 --- /dev/null +++ b/features/rewards-history/rewards-history-section/filters-and-export/use-rewards-history-export.ts @@ -0,0 +1,71 @@ +import { ValidatorRewardsEntity } from '@lidofinance/lido-csm-sdk'; +import { useOperatorKey } from 'modules/surveys-sdk'; +import { useTable } from 'providers/table-provider'; +import { useState } from 'react'; +import { exportToCsv, formatDate, formatPercent } from 'utils'; + +const headers = { + indexInReport: 'Index in Report', + validatorIndex: 'Validator Index', + pubkey: 'Public Key', + slashed: 'Slashed', + performance: 'Performance', + threshold: 'Threshold', + fee: 'Fee', + receivedShares: 'Received Shares', + receivedRewards: 'Received Rewards', + startTimestamp: 'Start Timestamp', + endTimestamp: 'End Timestamp', + refSlot: 'Ref Slot', + blockNumber: 'Block Number', +}; + +type CsvRow = Record; + +const transformData = (data: ValidatorRewardsEntity[]): CsvRow[] => { + return data.map((record) => ({ + indexInReport: String(record.indexInReport), + validatorIndex: record.validatorIndex, + pubkey: record.pubkey || '', + slashed: String(record.slashed), + performance: formatPercent(record.performance), + threshold: formatPercent(record.threshold), + fee: formatPercent(record.fee), + receivedShares: String(record.receivedShares), + receivedRewards: String(record.receivedRewards), + startTimestamp: String(record.startTimestamp), + endTimestamp: String(record.endTimestamp), + refSlot: String(record.refSlot), + blockNumber: String(record.blockNumber), + })); +}; + +export const useRewardsHistoryExport = () => { + const operatorKey = useOperatorKey(); + const { rawData } = useTable(); + const [isExporting, setIsExporting] = useState(false); + + const exportRewards = async () => { + try { + setIsExporting(true); + + const csvData = transformData(rawData); + const operator = operatorKey ?? ''; + const date = formatDate(Date.now(), 'yyyy-MM-dd'); + const filename = ['rewards-history', operator, date] + .filter(Boolean) + .join('-'); + + exportToCsv(csvData, headers, filename); + } catch (error) { + console.error('Failed to export rewards history:', error); + } finally { + setIsExporting(false); + } + }; + + return { + exportToCsv: exportRewards, + isExporting, + }; +}; diff --git a/features/rewards-history/rewards-history-section/index.ts b/features/rewards-history/rewards-history-section/index.ts new file mode 100644 index 000000000..d4edc82c2 --- /dev/null +++ b/features/rewards-history/rewards-history-section/index.ts @@ -0,0 +1 @@ +export * from './rewards-history-section'; diff --git a/features/rewards-history/rewards-history-section/performance.tsx b/features/rewards-history/rewards-history-section/performance.tsx new file mode 100644 index 000000000..5dcfad876 --- /dev/null +++ b/features/rewards-history/rewards-history-section/performance.tsx @@ -0,0 +1,14 @@ +import { ValidatorRewardsEntity } from '@lidofinance/lido-csm-sdk'; +import { FC } from 'react'; +import { formatPercent } from 'utils'; +import { PerformanceStyled } from './styles'; + +export const Performance: FC< + Pick +> = ({ performance, threshold, slashed }) => { + return ( + + {slashed ? 'Slashed' : formatPercent(performance)} + + ); +}; diff --git a/features/rewards-history/rewards-history-section/rewards-history-section.tsx b/features/rewards-history/rewards-history-section/rewards-history-section.tsx new file mode 100644 index 000000000..5f53be9d3 --- /dev/null +++ b/features/rewards-history/rewards-history-section/rewards-history-section.tsx @@ -0,0 +1,36 @@ +import { useNodeOperatorId, useOperatorRewardsHistory } from 'modules/web3'; +import { TablePagination, TableProvider } from 'providers/table-provider'; +import { FC } from 'react'; +import { Block, Stack, WhenLoaded } from 'shared/components'; +import { BondTableSwitcher } from 'shared/navigate'; +import { RewardsHistoryTable } from './rewards-history-table'; +import { sortFunctions } from './sort'; +import { FiltersAndExport } from './filters-and-export'; + +export const RewardsHistorySection: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + const { data, isPending } = useOperatorRewardsHistory(nodeOperatorId); + + return ( + + + + + + + + + + + + + ); +}; diff --git a/features/rewards-history/rewards-history-section/rewards-history-table.tsx b/features/rewards-history/rewards-history-section/rewards-history-table.tsx new file mode 100644 index 000000000..58ccf919d --- /dev/null +++ b/features/rewards-history/rewards-history-section/rewards-history-table.tsx @@ -0,0 +1,73 @@ +import { TOKENS, ValidatorRewardsEntity } from '@lidofinance/lido-csm-sdk'; +import { useTable } from 'providers/table-provider'; +import { FC } from 'react'; +import { CopyLink, Date, Pubkey } from 'shared/components'; +import { FormatToken } from 'shared/formatters'; +import { formatPercent } from 'utils'; +import { Performance } from './performance'; +import { DatesWrapper, Sort, TableStyle } from './styles'; + +export const RewardsHistoryTable: FC = () => { + const { data } = useTable(); + + return ( + + + + + Date period + + + Key + + + Fee + + + Performance + + + Threshold + + + Rewards + + + + + {data.map((record, index) => ( + + + + {' '} + — + + + + {record.pubkey ? ( + } + /> + ) : ( + record.validatorIndex + )} + + {formatPercent(record.fee)} + + + + {formatPercent(record.threshold)} + + + + + ))} + + + ); +}; diff --git a/features/rewards-history/rewards-history-section/sort.ts b/features/rewards-history/rewards-history-section/sort.ts new file mode 100644 index 000000000..ac95698ab --- /dev/null +++ b/features/rewards-history/rewards-history-section/sort.ts @@ -0,0 +1,35 @@ +import { ValidatorRewardsEntity } from '@lidofinance/lido-csm-sdk'; +import { SortCriteria, SortFunctions } from 'providers/table-provider'; + +const sortByDate: SortCriteria = (item) => [ + item.startTimestamp, +]; + +const sortByPubkey: SortCriteria = (item) => [ + item.pubkey, + item.validatorIndex, +]; + +const sortByFee: SortCriteria = (item) => [item.fee]; + +const sortByPerformance: SortCriteria = (item) => [ + item.slashed ? 0 : 1, + item.performance, +]; + +const sortByThreshold: SortCriteria = (item) => [ + item.threshold, +]; + +const sortByRewards: SortCriteria = (item) => [ + item.receivedRewards, +]; + +export const sortFunctions: SortFunctions = { + startTimestamp: sortByDate, + pubkey: sortByPubkey, + fee: sortByFee, + performance: sortByPerformance, + threshold: sortByThreshold, + receivedRewards: sortByRewards, +}; diff --git a/features/rewards-history/rewards-history-section/styles.ts b/features/rewards-history/rewards-history-section/styles.ts new file mode 100644 index 000000000..903d0fd15 --- /dev/null +++ b/features/rewards-history/rewards-history-section/styles.ts @@ -0,0 +1,42 @@ +import { SortButton } from 'providers/table-provider'; +import { Table } from 'shared/components'; +import { PubkeyContainerStyle } from 'shared/components/address/styles'; +import styled, { css } from 'styled-components'; +import { MEDIA_QUERY_XXL } from 'styles'; + +export const TableStyle = styled(Table)` + grid-template-columns: 2fr 3fr 1fr 1fr 1fr 2fr; + + tr { + ${MEDIA_QUERY_XXL} { + padding-inline: 16px; + gap: 12px; + + ${PubkeyContainerStyle} { + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; + } + } + } + + th:nth-child(n + 3):nth-child(-n + 6), + td:nth-child(n + 3):nth-child(-n + 6) { + justify-self: right; + text-align: right; + } +`; + +export const Sort = styled(SortButton).attrs({ variant: 'arrow' })``; + +export const DatesWrapper = styled.span` + white-space: nowrap; +`; + +export const PerformanceStyled = styled.span<{ $error?: boolean }>` + font-weight: 700; + + ${({ $error }) => + $error && + css` + color: var(--lido-color-error); + `} +`; diff --git a/features/rewards-history/rewards-history.tsx b/features/rewards-history/rewards-history.tsx new file mode 100644 index 000000000..cc60e028f --- /dev/null +++ b/features/rewards-history/rewards-history.tsx @@ -0,0 +1,13 @@ +import { ExtraWidth } from 'shared/components'; +import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; +import { RewardsHistorySection } from './rewards-history-section'; + +export const RewardsHistory = () => { + return ( + + + + + + ); +}; diff --git a/features/starter-pack/banner-operator-custom-addresses/banner-operator-custom-addresses.tsx b/features/starter-pack/banner-operator-custom-addresses/banner-operator-custom-addresses.tsx new file mode 100644 index 000000000..a82cdf09f --- /dev/null +++ b/features/starter-pack/banner-operator-custom-addresses/banner-operator-custom-addresses.tsx @@ -0,0 +1,25 @@ +import { moduleMeta } from 'consts/module'; +import { FC } from 'react'; +import { Banner } from 'shared/components'; +import { DescriptorId } from 'shared/node-operator'; +import { useOperatorCustomAddresses } from './use-operator-custom-addresses'; + +export const BannerOperatorCustomAddresses: FC = () => { + const [nodeOperatorId] = useOperatorCustomAddresses(); + + if (nodeOperatorId === undefined) { + return null; + } + + return ( + + To continue, connect to {moduleMeta.shortTitle} UI with the address you + specified as Reward/Manager Address for{' '} + or create a new Node Operator using + the currently connected address + + ); +}; diff --git a/features/starter-pack/banner-operator-custom-addresses/index.ts b/features/starter-pack/banner-operator-custom-addresses/index.ts new file mode 100644 index 000000000..5465cb67f --- /dev/null +++ b/features/starter-pack/banner-operator-custom-addresses/index.ts @@ -0,0 +1,2 @@ +export * from './banner-operator-custom-addresses'; +export * from './use-operator-custom-addresses'; diff --git a/features/starter-pack/banner-operator-custom-addresses/use-operator-custom-addresses.ts b/features/starter-pack/banner-operator-custom-addresses/use-operator-custom-addresses.ts new file mode 100644 index 000000000..163c2caff --- /dev/null +++ b/features/starter-pack/banner-operator-custom-addresses/use-operator-custom-addresses.ts @@ -0,0 +1,48 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useDappStatus } from 'modules/web3'; +import { useCallback, useMemo } from 'react'; +import { useSessionStorage } from 'shared/hooks'; +import { Address, isAddressEqual } from 'viem'; + +const EXPIRY_MS = 60 * 60 * 1000; // 1 hour +const STORAGE_KEY = 'operator-custom-address'; + +type StoredValue = { + nodeOperatorId: string; // serialized bigint + address: Address; + timestamp: number; +}; + +export const useOperatorCustomAddresses = () => { + const { address: walletAddress } = useDappStatus(); + + const [stored, setStored] = useSessionStorage( + STORAGE_KEY, + undefined, + ); + + const nodeOperatorId = useMemo(() => { + if (!stored?.nodeOperatorId) return undefined; + if (!walletAddress || !isAddressEqual(stored.address, walletAddress)) + return undefined; + if (Date.now() - stored.timestamp > EXPIRY_MS) return undefined; + return BigInt(stored.nodeOperatorId); + }, [stored, walletAddress]); + + const setOperatorCustomAddresses = useCallback( + (id: NodeOperatorId | undefined) => { + if (id === undefined || !walletAddress) { + setStored(undefined); + } else { + setStored({ + nodeOperatorId: id.toString(), + address: walletAddress, + timestamp: Date.now(), + }); + } + }, + [walletAddress, setStored], + ); + + return [nodeOperatorId, setOperatorCustomAddresses] as const; +}; diff --git a/features/starter-pack/cm-welcome-page.tsx b/features/starter-pack/cm-welcome-page.tsx new file mode 100644 index 000000000..80e93b6a9 --- /dev/null +++ b/features/starter-pack/cm-welcome-page.tsx @@ -0,0 +1,43 @@ +import { PATH } from 'consts'; +import { NavigateCMv1 } from 'features/welcome/navigate-cm-v1'; +import { useCuratedGatesEligibility, useInvites } from 'modules/web3'; +import { FC } from 'react'; +import { WelcomeSection } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { Navigate, SplashPage } from 'shared/navigate'; +import { BannerOperatorCustomAddresses } from './banner-operator-custom-addresses'; +import { BannerNotEligible } from './not-eligible/banner-not-eligible'; +import { BannerTryCsm } from './not-eligible/banner-try-csm'; + +export const CmWelcomePage: FC = () => { + const { data: isEligible, isPending } = useCuratedGatesEligibility( + undefined, + (data) => data.length > 0, + ); + const { data: invites, isPending: isPendingInvites } = useInvites(); + + if (isPending || isPendingInvites) { + return ; + } + + return ( + + {isEligible ? ( + + + + ) : invites?.length ? ( + + + + ) : ( + <> + + + + + + )} + + ); +}; diff --git a/features/starter-pack/consumed-banner/consumed-banner.tsx b/features/starter-pack/consumed-banner/consumed-banner.tsx deleted file mode 100644 index 53138eb67..000000000 --- a/features/starter-pack/consumed-banner/consumed-banner.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { FC } from 'react'; - -import { getExternalLinks } from 'consts/external-links'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { MatomoLink } from 'shared/components'; -import { BannerHeader, BlockStyled } from './styles'; - -const links = getExternalLinks(); - -export const ConsumedBanner: FC = () => ( - - - You have already joined CSM during Early Adoption period - -

          - You will be most welcome when the module is on the permissionless phase. -

          - - Learn more about Early Adoption. - -
          -); diff --git a/features/starter-pack/consumed-banner/index.ts b/features/starter-pack/consumed-banner/index.ts deleted file mode 100644 index 80d55dd6e..000000000 --- a/features/starter-pack/consumed-banner/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './consumed-banner'; diff --git a/features/starter-pack/consumed-banner/styles.ts b/features/starter-pack/consumed-banner/styles.ts deleted file mode 100644 index baece9a93..000000000 --- a/features/starter-pack/consumed-banner/styles.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Block, ThemeName } from '@lidofinance/lido-ui'; -import styled from 'styled-components'; - -export const BannerHeader = styled.h3` - font-size: ${({ theme }) => theme.fontSizesMap.sm}px; - line-height: ${({ theme }) => theme.fontSizesMap.xl}px; - font-weight: bold; -`; - -export const BlockStyled = styled(Block)` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spaceMap.md}px; - padding-inline: 10%; // @style - - text-align: center; - color: var(--lido-color-text); - font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; - line-height: ${({ theme }) => theme.fontSizesMap.lg}px; - - background: ${({ theme }) => - theme.name === ThemeName.light ? '#d8e0ea' : '#676772'}; - - a { - align-self: center; - } -`; diff --git a/features/starter-pack/create-operator-button.tsx b/features/starter-pack/create-operator-button.tsx new file mode 100644 index 000000000..e3f6cb2ad --- /dev/null +++ b/features/starter-pack/create-operator-button.tsx @@ -0,0 +1,29 @@ +import { Button } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { PATH } from 'consts/urls'; +import { useOperatorTypeModal } from 'features/create-node-operator/operator-type-modal/operator-type-modal'; +import { useShouldShowTypeModal } from 'features/create-node-operator/operator-type-modal/use-should-show-type-modal'; +import { FC } from 'react'; +import { LocalLink } from 'shared/navigate'; + +export const CreateOperatorButton: FC = () => { + const shouldShowModal = useShouldShowTypeModal(); + const { openModal } = useOperatorTypeModal(); + + return ( + <> + {shouldShowModal ? ( + + ) : ( + + + + )} + + ); +}; diff --git a/features/starter-pack/invites-redirect/index.ts b/features/starter-pack/invites-redirect/index.ts new file mode 100644 index 000000000..c9c75d6ec --- /dev/null +++ b/features/starter-pack/invites-redirect/index.ts @@ -0,0 +1 @@ +export * from './invites-redirect'; diff --git a/features/starter-pack/invites-redirect/invites-redirect.tsx b/features/starter-pack/invites-redirect/invites-redirect.tsx new file mode 100644 index 000000000..2690a7c18 --- /dev/null +++ b/features/starter-pack/invites-redirect/invites-redirect.tsx @@ -0,0 +1,23 @@ +import { PATH } from 'consts/urls'; +import { useInvites } from 'modules/web3'; +import { FC, useEffect } from 'react'; +import { useSessionStorage } from 'shared/hooks'; +import { useNavigate } from 'shared/navigate'; + +export const InvitesRedirect: FC = () => { + const { data: invites } = useInvites(); + const navigate = useNavigate(); + const [skipRedirect, setSkipRedirect] = useSessionStorage( + 'skip-invites-redirect', + false, + ); + + useEffect(() => { + if (invites?.length && !skipRedirect) { + setSkipRedirect(true); + void navigate(PATH.SETTINGS_INBOX); + } + }, [invites?.length, navigate, setSkipRedirect, skipRedirect]); + + return null; +}; diff --git a/features/starter-pack/not-eligible-banner/index.ts b/features/starter-pack/not-eligible-banner/index.ts deleted file mode 100644 index 91ff72cb4..000000000 --- a/features/starter-pack/not-eligible-banner/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './not-eligible-banner'; diff --git a/features/starter-pack/not-eligible-banner/not-eligible-banner.tsx b/features/starter-pack/not-eligible-banner/not-eligible-banner.tsx deleted file mode 100644 index d18711b6e..000000000 --- a/features/starter-pack/not-eligible-banner/not-eligible-banner.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { FC } from 'react'; - -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { MatomoLink } from 'shared/components'; -import { BannerHeader, BlockStyled } from './styles'; -import { getExternalLinks } from 'consts/external-links'; - -const links = getExternalLinks(); - -export const NotEligibleBanner: FC = () => ( - - - You are not eligible to join CSM during Early Adoption period - -

          - You will be most welcome when the module is on the permissionless phase. -

          - - Learn more about Early Adoption. - -
          -); diff --git a/features/starter-pack/not-eligible-banner/styles.ts b/features/starter-pack/not-eligible-banner/styles.ts deleted file mode 100644 index baece9a93..000000000 --- a/features/starter-pack/not-eligible-banner/styles.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Block, ThemeName } from '@lidofinance/lido-ui'; -import styled from 'styled-components'; - -export const BannerHeader = styled.h3` - font-size: ${({ theme }) => theme.fontSizesMap.sm}px; - line-height: ${({ theme }) => theme.fontSizesMap.xl}px; - font-weight: bold; -`; - -export const BlockStyled = styled(Block)` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spaceMap.md}px; - padding-inline: 10%; // @style - - text-align: center; - color: var(--lido-color-text); - font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; - line-height: ${({ theme }) => theme.fontSizesMap.lg}px; - - background: ${({ theme }) => - theme.name === ThemeName.light ? '#d8e0ea' : '#676772'}; - - a { - align-self: center; - } -`; diff --git a/features/starter-pack/not-eligible/banner-not-eligible.tsx b/features/starter-pack/not-eligible/banner-not-eligible.tsx new file mode 100644 index 000000000..0905685e6 --- /dev/null +++ b/features/starter-pack/not-eligible/banner-not-eligible.tsx @@ -0,0 +1,37 @@ +import { Text } from '@lidofinance/lido-ui'; +import { LIDO_OPERATOR_PORTAL_CM } from 'consts'; +import { FC } from 'react'; +import { Banner, MatomoLink, Stack } from 'shared/components'; +import { FailIcon } from 'shared/transaction-modal/tx-stages-basic/icons-styles'; +import { Disconnect } from 'shared/wallet'; + +export const BannerNotEligible: FC = () => { + return ( + + + + You’re not eligible to create a Node Operator + + + } + > + +
          + The Curated Module v2 consists of allow-listed independent + professional staking organizations and Ethereum client teams, which + operate validators using the protocol. For a detailed description of + the module, follow{' '} + + the link + + . +
          + +
          +
          + ); +}; diff --git a/features/starter-pack/not-eligible/banner-try-csm.tsx b/features/starter-pack/not-eligible/banner-try-csm.tsx new file mode 100644 index 000000000..204a9fb49 --- /dev/null +++ b/features/starter-pack/not-eligible/banner-try-csm.tsx @@ -0,0 +1,46 @@ +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; +import { Button, DarkThemeProvider } from '@lidofinance/lido-ui'; +import { + CSM_MAINNET_LINK, + CSM_TESTNET_LINK, + LIDO_OPERATOR_PORTAL_BASE, +} from 'consts'; +import { useDappStatus } from 'modules/web3'; +import { FC } from 'react'; +import { Banner, MatomoLink, Stack } from 'shared/components'; + +export const BannerTryCsm: FC = () => { + const { chainId } = useDappStatus(); + + const isMainnet = chainId === CHAINS.Mainnet; + + return ( + + + +
          + The Community Staking Module (CSM) is a permissionless staking + module aimed at attracting community stakers to participate in the + Lido protocol as Node Operators. For a detailed description of the + module, follow{' '} + + the link + + . +
          + + + +
          +
          +
          + ); +}; diff --git a/features/starter-pack/paused-banner/paused-banner.tsx b/features/starter-pack/paused-banner/paused-banner.tsx index ebfa1e5c9..ae84094e6 100644 --- a/features/starter-pack/paused-banner/paused-banner.tsx +++ b/features/starter-pack/paused-banner/paused-banner.tsx @@ -1,23 +1,14 @@ import { FC } from 'react'; import { BannerHeader, BlockStyled } from './styles'; -import { getConfig } from 'config'; -import { CHAINS } from 'consts/chains'; -import { HoleskyBanner } from 'features/welcome/holesky-banner'; - -const { defaultChain } = getConfig(); export const PausedBanner: FC = () => { - if (defaultChain === CHAINS.Holesky) { - return ; - } - return ( CSM is paused

          This means that uploading new keys is currently not possible, but Node - Operator stats can be viewed. + Operator stats can be viewed

          ); diff --git a/features/starter-pack/stacter-pack-section/required-bond-amount.tsx b/features/starter-pack/stacter-pack-section/required-bond-amount.tsx deleted file mode 100644 index 85b897e7e..000000000 --- a/features/starter-pack/stacter-pack-section/required-bond-amount.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Box, InlineLoader } from '@lidofinance/lido-ui'; -import { getConfig } from 'config'; -import { CHAINS } from 'consts/chains'; -import { FC } from 'react'; -import { FormatToken } from 'shared/formatters'; -import { useCsmCurveId, useCsmEarlyAdoption, useCurveInfo } from 'shared/hooks'; - -const { defaultChain } = getConfig(); - -export const RequiredBondAmount: FC = () => { - const isMainnet = defaultChain === CHAINS.Mainnet; - const { data: ea } = useCsmEarlyAdoption(); - const { data: curveId, initialLoading: curveLoading } = useCsmCurveId( - !!ea?.proof || true, - ); - const { data: curveInfo, initialLoading: curveInfoLoading } = - useCurveInfo(curveId); - const amount = curveInfo?.points[0]; - - return ( - <> - {curveLoading || curveInfoLoading ? ( - - - - ) : ( - - )} - - ); -}; diff --git a/features/starter-pack/stacter-pack-section/starter-pack-section.tsx b/features/starter-pack/stacter-pack-section/starter-pack-section.tsx index 16d6ffa18..250da06c9 100644 --- a/features/starter-pack/stacter-pack-section/starter-pack-section.tsx +++ b/features/starter-pack/stacter-pack-section/starter-pack-section.tsx @@ -1,24 +1,26 @@ import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; import { FC, PropsWithChildren } from 'react'; -import { MatomoLink } from 'shared/components'; +import { FaqBondAmount, MatomoLink } from 'shared/components'; import { Partners } from './partners'; import { Step } from './step'; import { BlockStyled, Heading, Steps } from './styles'; -import { RequiredBondAmount } from './required-bond-amount'; import { ABOUT_DEPOSIT_DATA_LINK, HOW_TO_GENERATE_DEPOSIT_DATA_LINK, PREPARE_HARDWARE_LINK, + LIDO_OPERATOR_PORTAL_BASE, + LIDO_OPERATOR_PORTAL_BONDS_INFO, } from 'consts/external-links'; export const StarterPackSection: FC = ({ children }) => ( - +

          CSM node operator starter pack

          Make sure you’ve completed all the basic steps before joining the{' '} Community Staking Module @@ -27,11 +29,11 @@ export const StarterPackSection: FC = ({ children }) => ( - (stETH / wstETH equivalent) is required for the - first validator + (stETH / wstETH equivalent) is required for the first + validator
          Learn more @@ -40,8 +42,9 @@ export const StarterPackSection: FC = ({ children }) => ( Run{' '} your own hardware {' '} @@ -50,6 +53,7 @@ export const StarterPackSection: FC = ({ children }) => ( Do it{' '} @@ -63,6 +67,7 @@ export const StarterPackSection: FC = ({ children }) => (
          Follow the{' '} diff --git a/features/starter-pack/starter-pack-page.tsx b/features/starter-pack/starter-pack-page.tsx index 67ebd8791..3ab198a68 100644 --- a/features/starter-pack/starter-pack-page.tsx +++ b/features/starter-pack/starter-pack-page.tsx @@ -1,16 +1,17 @@ import { FC } from 'react'; import { Layout } from 'shared/layout'; +import { InvitesRedirect } from './invites-redirect'; import { StarterPack } from './starter-pack'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { Faq } from 'shared/components'; +import { FAQ_MAIN } from 'faq'; export const StarterPackPage: FC = () => { return ( - + + + ); }; diff --git a/features/starter-pack/starter-pack.tsx b/features/starter-pack/starter-pack.tsx index 0649e5ddf..59e17e138 100644 --- a/features/starter-pack/starter-pack.tsx +++ b/features/starter-pack/starter-pack.tsx @@ -1,52 +1,29 @@ -import { Button } from '@lidofinance/lido-ui'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { PATH } from 'consts/urls'; -import { TryCSM } from 'features/welcome/try-csm'; -import Link from 'next/link'; -import { FC, useCallback } from 'react'; -import { Faq } from 'shared/components'; -import { useCsmEarlyAdoption } from 'shared/hooks'; -import { useCsmPaused, useCsmPublicRelease } from 'shared/hooks/useCsmStatus'; -import { trackMatomoEvent } from 'utils'; -import { ConsumedBanner } from './consumed-banner'; -import { NotEligibleBanner } from './not-eligible-banner/not-eligible-banner'; +import { TryOtherNetwork } from 'features/welcome/try-other-network'; +import { useSmStatus } from 'modules/web3'; +import { FC } from 'react'; +import { BannerOperatorCustomAddresses } from './banner-operator-custom-addresses'; +import { CreateOperatorButton } from './create-operator-button'; import { PausedBanner } from './paused-banner'; import { StarterPackSection } from './stacter-pack-section'; export const StarterPack: FC = () => { - const { data: paused } = useCsmPaused(); - const { data: isPublicRelease } = useCsmPublicRelease(); - const { data: ea } = useCsmEarlyAdoption(); - - const handleClick = useCallback(() => { - trackMatomoEvent(MATOMO_CLICK_EVENTS_TYPES.starterPackCreateNodeOperator); - }, []); + const { data: status } = useSmStatus(); let content = ( - - - + ); - if (!isPublicRelease && ea?.consumed) { - content = ; - } - - if (!isPublicRelease && !ea?.proof) { - content = ; - } - - if (paused?.isPaused || paused?.isAccountingPaused) { + if (status?.isPaused) { content = ; } return ( <> + {content} - - + ); }; diff --git a/features/stealing/index.ts b/features/stealing/index.ts deleted file mode 100644 index d8cba07b2..000000000 --- a/features/stealing/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './stealing-cancel-page'; -export * from './stealing-cancel'; -export * from './stealing-report-page'; -export * from './stealing-report'; diff --git a/features/stealing/locked-section/locked-section.tsx b/features/stealing/locked-section/locked-section.tsx deleted file mode 100644 index e73f1f1a7..000000000 --- a/features/stealing/locked-section/locked-section.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Block } from '@lidofinance/lido-ui'; -import { FC } from 'react'; -import { WhenLoaded } from 'shared/components'; -import { useNodeOperatorsWithLockedBond } from 'shared/hooks'; -import { LockedTable } from './locked-table'; - -export const LockedSection: FC = () => { - const { data, initialLoading: loading } = useNodeOperatorsWithLockedBond(); - - return ( - - - - - - ); -}; diff --git a/features/stealing/locked-section/locked-table.tsx b/features/stealing/locked-section/locked-table.tsx deleted file mode 100644 index 07ff258dc..000000000 --- a/features/stealing/locked-section/locked-table.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Tbody, Td, Text, Th, Thead, Tr } from '@lidofinance/lido-ui'; -import { TOKENS } from 'consts/tokens'; -import { FC } from 'react'; -import { Stack } from 'shared/components'; -import { FormatToken } from 'shared/formatters'; -import { LockedOperator } from 'shared/hooks'; -import { TableStyle } from './styles'; - -type Props = { - data?: LockedOperator[]; - offset?: number; -}; - -export const LockedTable: FC = ({ data, offset = 0 }) => ( - - - - - Node Operator ID - Locked bond amount - - - - {data?.map(([id, amount], index) => ( - - - - {id} - - - - - - - ))} - - - -); diff --git a/features/stealing/locked-section/styles.tsx b/features/stealing/locked-section/styles.tsx deleted file mode 100644 index c2fa66e88..000000000 --- a/features/stealing/locked-section/styles.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Table } from '@lidofinance/lido-ui'; -import styled from 'styled-components'; - -export const TableStyle = styled(Table)` - margin: -32px -32px; - - thead tr::before, - thead tr::after, - th { - border-top: none; - } - - th { - padding: 24px 8px 16px 8px; - min-width: 40px; - } - - td { - padding: 12px 8px; - } - - th > div { - display: flex; - gap: ${({ theme }) => theme.spaceMap.xs}px; - align-items: center; - - svg { - width: 16px; - } - } - - td { - border-bottom: none; - } - - tbody tr:nth-child(odd) { - background-color: var(--lido-color-accentControlBg); - } -`; diff --git a/features/stealing/stealing-cancel-form/context/index.ts b/features/stealing/stealing-cancel-form/context/index.ts deleted file mode 100644 index ca29f3cc2..000000000 --- a/features/stealing/stealing-cancel-form/context/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './stealing-cancel-form-provider'; -export * from './types'; diff --git a/features/stealing/stealing-cancel-form/context/stealing-cancel-form-provider.tsx b/features/stealing/stealing-cancel-form/context/stealing-cancel-form-provider.tsx deleted file mode 100644 index b392eac3e..000000000 --- a/features/stealing/stealing-cancel-form/context/stealing-cancel-form-provider.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { FC, PropsWithChildren, useMemo } from 'react'; -import { FormProvider, useForm } from 'react-hook-form'; -import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormControllerRetry, - useFormData, -} from 'shared/hook-form/form-controller'; -import { - StealingCancelFormNetworkData, - type StealingCancelFormInputType, -} from './types'; -import { useStealingCancelFormNetworkData } from './use-stealing-cancel-form-network-data'; -import { useStealingCancelSubmit } from './use-stealing-cancel-submit'; -import { useStealingCancelValidation } from './use-stealing-cancel-validation'; -import { useFormMaxAmount } from './use-form-max-amount'; - -export const useStealingCancelFormData = - useFormData; - -export const StealingCancelFormProvider: FC = ({ - children, -}) => { - const [networkData, revalidate] = useStealingCancelFormNetworkData(); - const validationResolver = useStealingCancelValidation(networkData); - - // TODO: validate (max amount) - const formObject = useForm({ - defaultValues: { - amount: undefined, - }, - resolver: validationResolver, - mode: 'onChange', - }); - - useFormMaxAmount(formObject); - - const { retryEvent, retryFire } = useFormControllerRetry(); - - const { stealingCancel } = useStealingCancelSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - StealingCancelFormInputType, - StealingCancelFormNetworkData - > = useMemo( - () => ({ - onSubmit: stealingCancel, - retryEvent, - }), - [stealingCancel, retryEvent], - ); - - return ( - - - - {children} - - - - ); -}; diff --git a/features/stealing/stealing-cancel-form/context/types.ts b/features/stealing/stealing-cancel-form/context/types.ts deleted file mode 100644 index 124015fdf..000000000 --- a/features/stealing/stealing-cancel-form/context/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BigNumber } from 'ethers'; -import { LoadingRecord, NodeOperatorId } from 'types'; - -export type StealingCancelFormInputType = { - amount?: BigNumber; - nodeOperatorId?: NodeOperatorId; - maxAmount?: BigNumber; -}; - -export type StealingCancelFormNetworkData = { - etherBalance?: BigNumber; - nodeOperatorsCount?: BigNumber; - loading: LoadingRecord<'etherBalance' | 'nodeOperatorsCount'>; -}; diff --git a/features/stealing/stealing-cancel-form/context/use-form-max-amount.ts b/features/stealing/stealing-cancel-form/context/use-form-max-amount.ts deleted file mode 100644 index 26eb65e92..000000000 --- a/features/stealing/stealing-cancel-form/context/use-form-max-amount.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { useEffect } from 'react'; -import { UseFormReturn } from 'react-hook-form'; -import { useNodeOperatorLockAmount } from 'shared/hooks'; -import { StealingCancelFormInputType } from './types'; - -export const useFormMaxAmount = ({ - watch, - setValue, - trigger, -}: UseFormReturn) => { - const nodeOperatorId = watch('nodeOperatorId'); - - const { data: maxAmount } = useNodeOperatorLockAmount(nodeOperatorId); - - useEffect(() => { - void trigger('maxAmount'); - }, [nodeOperatorId, trigger]); - - useEffect(() => { - setValue('maxAmount', maxAmount, { shouldValidate: true }); - }, [maxAmount, setValue]); -}; diff --git a/features/stealing/stealing-cancel-form/context/use-stealing-cancel-form-network-data.tsx b/features/stealing/stealing-cancel-form/context/use-stealing-cancel-form-network-data.tsx deleted file mode 100644 index bf3a88a5e..000000000 --- a/features/stealing/stealing-cancel-form/context/use-stealing-cancel-form-network-data.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { useEthereumBalance } from '@lido-sdk/react'; -import { STRATEGY_LAZY } from 'consts/swr-strategies'; -import { useCallback, useMemo } from 'react'; -import { useNodeOperatorsCount } from 'shared/hooks'; -import { type StealingCancelFormNetworkData } from './types'; - -export const useStealingCancelFormNetworkData = (): [ - StealingCancelFormNetworkData, - () => Promise, -] => { - const { - data: etherBalance, - update: updateEtherBalance, - initialLoading: isEtherBalanceLoading, - } = useEthereumBalance(undefined, STRATEGY_LAZY); - - const { - data: nodeOperatorsCount, - initialLoading: isNodeOperatorsCountLoading, - } = useNodeOperatorsCount(); - - const revalidate = useCallback(async () => { - await Promise.allSettled([updateEtherBalance()]); - }, [updateEtherBalance]); - - const loading = useMemo( - () => ({ - isEtherBalanceLoading, - isNodeOperatorsCountLoading, - }), - [isEtherBalanceLoading, isNodeOperatorsCountLoading], - ); - - return [ - { - etherBalance, - nodeOperatorsCount, - loading, - }, - revalidate, - ]; -}; diff --git a/features/stealing/stealing-cancel-form/context/use-stealing-cancel-submit.ts b/features/stealing/stealing-cancel-form/context/use-stealing-cancel-submit.ts deleted file mode 100644 index ef0f15776..000000000 --- a/features/stealing/stealing-cancel-form/context/use-stealing-cancel-submit.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { BigNumber } from 'ethers'; -import { useCallback } from 'react'; -import invariant from 'tiny-invariant'; - -import { useCSModuleWeb3, useSendTx } from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; -import { runWithTransactionLogger } from 'utils'; -import { StealingCancelFormInputType } from '.'; -import { useTxModalStagesStealingCancel } from '../hooks/use-tx-modal-stages-stealing-cancel'; - -type UseStealingCancelOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type StealingCancelMethodParams = { - nodeOperatorId: NodeOperatorId; - amount: BigNumber; -}; - -const useStealingCancelTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async (params: StealingCancelMethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - return { - tx: await CSModuleWeb3.populateTransaction.cancelELRewardsStealingPenalty( - params.nodeOperatorId, - params.amount, - ), - txName: 'cancelELRewardsStealingPenalty', - }; - }, - [CSModuleWeb3], - ); -}; - -export const useStealingCancelSubmit = ({ - onConfirm, - onRetry, -}: UseStealingCancelOptions) => { - const { txModalStages } = useTxModalStagesStealingCancel(); - - const getTx = useStealingCancelTx(); - const sendTx = useSendTx(); - - const stealingCancel = useCallback( - async ({ - amount, - nodeOperatorId, - }: StealingCancelFormInputType): Promise => { - invariant(amount, 'BondAmount is not defined'); - invariant(nodeOperatorId, 'NodeOperatorId is not defined'); - - try { - txModalStages.sign({ amount, nodeOperatorId }); - - const tx = await getTx({ - nodeOperatorId, - amount, - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'StealingCancel signing', - () => sendTx(tx), - ); - - txModalStages.pending({ amount, nodeOperatorId }, txHash); - - await runWithTransactionLogger( - 'StealingCancel block confirmation', - waitTx, - ); - - await onConfirm?.(); - - txModalStages.success({ amount, nodeOperatorId }, txHash); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [getTx, txModalStages, onConfirm, sendTx, onRetry], - ); - - return { - stealingCancel, - }; -}; diff --git a/features/stealing/stealing-cancel-form/context/use-stealing-cancel-validation.ts b/features/stealing/stealing-cancel-form/context/use-stealing-cancel-validation.ts deleted file mode 100644 index afcf74876..000000000 --- a/features/stealing/stealing-cancel-form/context/use-stealing-cancel-validation.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { TOKENS } from 'consts/tokens'; -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; -import { - handleResolverValidationError, - validateBignumberMax, - validateEtherAmount, - validateNodeOperatorId, -} from 'shared/hook-form/validation'; -import { useAwaitNetworkData } from 'shared/hooks'; -import invariant from 'tiny-invariant'; -import type { - StealingCancelFormInputType, - StealingCancelFormNetworkData, -} from './types'; -import { getTokenDisplayName } from 'utils'; -import { formatEther } from '@ethersproject/units'; -import { FormatToken } from 'shared/formatters'; - -export const useStealingCancelValidation = ( - networkData: StealingCancelFormNetworkData, -) => { - const dataPromise = useAwaitNetworkData(networkData); - - return useCallback>( - async (values, _, options) => { - try { - const { amount, nodeOperatorId, maxAmount } = values; - - const { nodeOperatorsCount, etherBalance } = await dataPromise; - - invariant(etherBalance); - invariant(nodeOperatorsCount); - - if (options.names?.includes('nodeOperatorId')) - validateNodeOperatorId( - 'nodeOperatorId', - nodeOperatorId, - nodeOperatorsCount, - ); - - if (options.names?.includes('amount')) { - validateEtherAmount('amount', amount, TOKENS.ETH); - - if (amount && maxAmount) - validateBignumberMax( - 'amount', - amount, - maxAmount, - `Entered amount exceeds locked bond of ${formatEther(maxAmount)} ${getTokenDisplayName(TOKENS.ETH)}`, - ); - FormatToken; - } - - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError( - error, - 'StealingCancelForm', - 'amount', - ); - } - }, - [dataPromise], - ); -}; diff --git a/features/stealing/stealing-cancel-form/controls/amount-input.tsx b/features/stealing/stealing-cancel-form/controls/amount-input.tsx deleted file mode 100644 index 1152185ca..000000000 --- a/features/stealing/stealing-cancel-form/controls/amount-input.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { TOKENS } from 'consts/tokens'; -import { useWatch } from 'react-hook-form'; -import { FormTitle } from 'shared/components'; -import { TokenAmountInputHookForm } from 'shared/hook-form/controls'; -import { StealingCancelFormInputType } from '../context'; - -export const AmountInput: React.FC = () => { - const maxAmount = useWatch({ - name: 'maxAmount', - }); - - return ( - <> - Enter cancellation amount - - - ); -}; diff --git a/features/stealing/stealing-cancel-form/controls/submit-button.tsx b/features/stealing/stealing-cancel-form/controls/submit-button.tsx deleted file mode 100644 index dab5c52b5..000000000 --- a/features/stealing/stealing-cancel-form/controls/submit-button.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { SubmitButtonHookForm } from 'shared/hook-form/controls'; - -export const SubmitButton = () => { - // TODO: disable - return ( - - Cancel stealing - - ); -}; diff --git a/features/stealing/stealing-cancel-form/hooks/use-tx-modal-stages-stealing-cancel.tsx b/features/stealing/stealing-cancel-form/hooks/use-tx-modal-stages-stealing-cancel.tsx deleted file mode 100644 index 1199d46df..000000000 --- a/features/stealing/stealing-cancel-form/hooks/use-tx-modal-stages-stealing-cancel.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import type { BigNumber } from 'ethers'; - -import { TOKENS } from 'consts/tokens'; -import { - TransactionModalTransitStage, - TxAmount, - TxStagePending, - TxStageSign, - TxStageSuccess, - getGeneralTransactionModalStages, - useTransactionModalStage, -} from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; - -type Props = { - amount: BigNumber; - nodeOperatorId: NodeOperatorId; -}; - -const getTxModalStagesStealingCancel = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: ({ amount, nodeOperatorId }: Props) => - transitStage( - - Node Operator ID: {nodeOperatorId} -
          - Amount: - - } - />, - ), - - pending: ({ amount, nodeOperatorId }: Props, txHash?: string) => - transitStage( - - Node Operator ID: {nodeOperatorId} -
          - Amount: - - } - />, - ), - - success: ({ amount, nodeOperatorId }: Props, txHash?: string) => - transitStage( - - Node Operator ID: {nodeOperatorId} -
          - Amount: - - } - />, - { - isClosableOnLedger: true, - }, - ), -}); - -export const useTxModalStagesStealingCancel = () => { - return useTransactionModalStage(getTxModalStagesStealingCancel); -}; diff --git a/features/stealing/stealing-cancel-form/index.ts b/features/stealing/stealing-cancel-form/index.ts deleted file mode 100644 index 68d85c4b4..000000000 --- a/features/stealing/stealing-cancel-form/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { StealingCancelForm } from './stealing-cancel-form'; diff --git a/features/stealing/stealing-cancel-form/stealing-cancel-form-loader.tsx b/features/stealing/stealing-cancel-form/stealing-cancel-form-loader.tsx deleted file mode 100644 index 96c8c8347..000000000 --- a/features/stealing/stealing-cancel-form/stealing-cancel-form-loader.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { FC, PropsWithChildren } from 'react'; -import { useFormState } from 'react-hook-form'; -import { WhenLoaded } from 'shared/components'; -import { StealingCancelFormInputType } from './context'; - -export const StealingCancelFormLoader: FC = ({ - children, -}) => { - const { isLoading } = useFormState(); - - return {children}; -}; diff --git a/features/stealing/stealing-cancel-form/stealing-cancel-form.tsx b/features/stealing/stealing-cancel-form/stealing-cancel-form.tsx deleted file mode 100644 index 4cb006592..000000000 --- a/features/stealing/stealing-cancel-form/stealing-cancel-form.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { FC, memo } from 'react'; - -import { StealingCancelFormProvider } from './context'; - -import { FormBlock } from 'shared/components'; -import { FormControllerStyled } from 'shared/hook-form/form-controller'; -import { AmountInput } from './controls/amount-input'; -import { NodeOperatorInput } from './controls/node-operator-input'; -import { SubmitButton } from './controls/submit-button'; -import { StealingCancelFormLoader } from './stealing-cancel-form-loader'; - -export const StealingCancelForm: FC = memo(() => { - return ( - - - - - - - - - - - - ); -}); diff --git a/features/stealing/stealing-cancel-page.tsx b/features/stealing/stealing-cancel-page.tsx deleted file mode 100644 index 86b9a210b..000000000 --- a/features/stealing/stealing-cancel-page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { FC } from 'react'; - -import { Layout } from 'shared/layout'; -import { StealingPageSwitcher } from 'shared/navigate'; -import { StealingCancel } from './stealing-cancel'; - -export const StealingCancelPage: FC = () => ( - - - - -); diff --git a/features/stealing/stealing-cancel.tsx b/features/stealing/stealing-cancel.tsx deleted file mode 100644 index 45655732b..000000000 --- a/features/stealing/stealing-cancel.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; - -import { StealingCancelForm } from './stealing-cancel-form'; -import { LockedSection } from './locked-section'; - -export const StealingCancel = () => { - const key = useWeb3Key(); - return ( - <> - - - - - - ); -}; diff --git a/features/stealing/stealing-report-form/context/index.ts b/features/stealing/stealing-report-form/context/index.ts deleted file mode 100644 index 6cbe42e4b..000000000 --- a/features/stealing/stealing-report-form/context/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './stealing-report-form-provider'; -export * from './types'; diff --git a/features/stealing/stealing-report-form/context/stealing-report-form-provider.tsx b/features/stealing/stealing-report-form/context/stealing-report-form-provider.tsx deleted file mode 100644 index 1397bca59..000000000 --- a/features/stealing/stealing-report-form/context/stealing-report-form-provider.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { FC, PropsWithChildren, useMemo } from 'react'; -import { FormProvider, useForm } from 'react-hook-form'; -import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormControllerRetry, - useFormData, -} from 'shared/hook-form/form-controller'; -import { - StealingReportFormNetworkData, - type StealingReportFormInputType, -} from './types'; -import { useStealingReportFormNetworkData } from './use-stealing-report-form-network-data'; -import { useStealingReportSubmit } from './use-stealing-report-submit'; -import { useStealingReportValidation } from './use-stealing-report-validation'; - -export const useStealingReportFormData = - useFormData; - -export const StealingReportFormProvider: FC = ({ - children, -}) => { - const [networkData, revalidate] = useStealingReportFormNetworkData(); - const validationResolver = useStealingReportValidation(networkData); - - // TODO: validate (max amount) - const formObject = useForm({ - defaultValues: { - amount: undefined, - }, - resolver: validationResolver, - mode: 'onChange', - }); - - const { retryEvent, retryFire } = useFormControllerRetry(); - - const { stealingReport } = useStealingReportSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - StealingReportFormInputType, - StealingReportFormNetworkData - > = useMemo( - () => ({ - onSubmit: stealingReport, - retryEvent, - }), - [stealingReport, retryEvent], - ); - - return ( - - - - {children} - - - - ); -}; diff --git a/features/stealing/stealing-report-form/context/types.ts b/features/stealing/stealing-report-form/context/types.ts deleted file mode 100644 index 0588ea1a6..000000000 --- a/features/stealing/stealing-report-form/context/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BigNumber } from 'ethers'; -import { LoadingRecord, NodeOperatorId } from 'types'; - -export type StealingReportFormInputType = { - amount?: BigNumber; - nodeOperatorId?: NodeOperatorId; - blockhash?: string; -}; - -export type StealingReportFormNetworkData = { - etherBalance?: BigNumber; - nodeOperatorsCount?: BigNumber; - loading: LoadingRecord<'etherBalance' | 'nodeOperatorsCount'>; -}; diff --git a/features/stealing/stealing-report-form/context/use-stealing-report-form-network-data.tsx b/features/stealing/stealing-report-form/context/use-stealing-report-form-network-data.tsx deleted file mode 100644 index 5ca6b4737..000000000 --- a/features/stealing/stealing-report-form/context/use-stealing-report-form-network-data.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { useEthereumBalance } from '@lido-sdk/react'; -import { STRATEGY_LAZY } from 'consts/swr-strategies'; -import { useCallback, useMemo } from 'react'; -import { useNodeOperatorsCount } from 'shared/hooks'; -import { type StealingReportFormNetworkData } from './types'; - -export const useStealingReportFormNetworkData = (): [ - StealingReportFormNetworkData, - () => Promise, -] => { - const { - data: etherBalance, - update: updateEtherBalance, - initialLoading: isEtherBalanceLoading, - } = useEthereumBalance(undefined, STRATEGY_LAZY); - - const { - data: nodeOperatorsCount, - initialLoading: isNodeOperatorsCountLoading, - } = useNodeOperatorsCount(); - - const revalidate = useCallback(async () => { - await Promise.allSettled([updateEtherBalance()]); - }, [updateEtherBalance]); - - const loading = useMemo( - () => ({ - isEtherBalanceLoading, - isNodeOperatorsCountLoading, - }), - [isEtherBalanceLoading, isNodeOperatorsCountLoading], - ); - - return [ - { - etherBalance, - nodeOperatorsCount, - loading, - }, - revalidate, - ]; -}; diff --git a/features/stealing/stealing-report-form/context/use-stealing-report-submit.ts b/features/stealing/stealing-report-form/context/use-stealing-report-submit.ts deleted file mode 100644 index f9a8f4b49..000000000 --- a/features/stealing/stealing-report-form/context/use-stealing-report-submit.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { BigNumber } from 'ethers'; -import { useCallback } from 'react'; -import invariant from 'tiny-invariant'; - -import { useCSModuleWeb3, useSendTx } from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; -import { runWithTransactionLogger } from 'utils'; -import { StealingReportFormInputType } from '.'; -import { useTxModalStagesStealingReport } from '../hooks/use-tx-modal-stages-stealing-report'; - -type UseStealingReportOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type StealingReportMethodParams = { - nodeOperatorId: NodeOperatorId; - amount: BigNumber; - blockhash: string; -}; - -const useStealingReportTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async (params: StealingReportMethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - return { - tx: await CSModuleWeb3.populateTransaction.reportELRewardsStealingPenalty( - params.nodeOperatorId, - params.blockhash, - params.amount, - ), - txName: 'reportELRewardsStealingPenalty', - }; - }, - [CSModuleWeb3], - ); -}; - -export const useStealingReportSubmit = ({ - onConfirm, - onRetry, -}: UseStealingReportOptions) => { - const { txModalStages } = useTxModalStagesStealingReport(); - - const getTx = useStealingReportTx(); - const sendTx = useSendTx(); - - const stealingReport = useCallback( - async ({ - amount, - nodeOperatorId, - blockhash, - }: StealingReportFormInputType): Promise => { - invariant(amount, 'BondAmount is not defined'); - invariant(nodeOperatorId, 'NodeOperatorId is not defined'); - invariant(blockhash, 'BlockHash is not defined'); - - try { - txModalStages.sign({ amount, nodeOperatorId, blockhash }); - - const tx = await getTx({ - nodeOperatorId, - amount, - blockhash, - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'StealingReport signing', - () => sendTx(tx), - ); - - txModalStages.pending({ amount, nodeOperatorId, blockhash }, txHash); - - await runWithTransactionLogger( - 'StealingReport block confirmation', - waitTx, - ); - - await onConfirm?.(); - - txModalStages.success({ amount, nodeOperatorId, blockhash }, txHash); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [getTx, txModalStages, onConfirm, sendTx, onRetry], - ); - - return { - stealingReport, - }; -}; diff --git a/features/stealing/stealing-report-form/context/use-stealing-report-validation.ts b/features/stealing/stealing-report-form/context/use-stealing-report-validation.ts deleted file mode 100644 index 0a1c6249c..000000000 --- a/features/stealing/stealing-report-form/context/use-stealing-report-validation.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { TOKENS } from 'consts/tokens'; -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; -import { - handleResolverValidationError, - validateEtherAmount, - validateHash, - validateNodeOperatorId, -} from 'shared/hook-form/validation'; -import { useAwaitNetworkData } from 'shared/hooks'; -import invariant from 'tiny-invariant'; -import type { - StealingReportFormInputType, - StealingReportFormNetworkData, -} from './types'; - -export const useStealingReportValidation = ( - networkData: StealingReportFormNetworkData, -) => { - const dataPromise = useAwaitNetworkData(networkData); - - return useCallback>( - async (values, _, options) => { - try { - const { amount, nodeOperatorId, blockhash } = values; - - const { nodeOperatorsCount, etherBalance } = await dataPromise; - - invariant(etherBalance); - invariant(nodeOperatorsCount); - - if (options.names?.includes('nodeOperatorId')) - validateNodeOperatorId( - 'nodeOperatorId', - nodeOperatorId, - nodeOperatorsCount, - ); - - if (options.names?.includes('amount')) - validateEtherAmount('amount', amount, TOKENS.ETH); - - if (options.names?.includes('blockhash')) - validateHash('blockhash', blockhash); - - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError( - error, - 'StealingReportForm', - 'amount', - ); - } - }, - [dataPromise], - ); -}; diff --git a/features/stealing/stealing-report-form/controls/amount-input.tsx b/features/stealing/stealing-report-form/controls/amount-input.tsx deleted file mode 100644 index 9bfd79bb8..000000000 --- a/features/stealing/stealing-report-form/controls/amount-input.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { TOKENS } from 'consts/tokens'; -import { FormTitle } from 'shared/components'; -import { TokenAmountInputHookForm } from 'shared/hook-form/controls'; - -export const AmountInput: React.FC = () => { - return ( - <> - Enter stealing amount - - - ); -}; diff --git a/features/stealing/stealing-report-form/controls/blockhash-input.tsx b/features/stealing/stealing-report-form/controls/blockhash-input.tsx deleted file mode 100644 index 840cbb5e4..000000000 --- a/features/stealing/stealing-report-form/controls/blockhash-input.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { FormTitle, Note } from 'shared/components'; -import { TextInputHookForm } from 'shared/hook-form/controls'; - -export const BlockhashInput: React.FC = () => { - return ( - <> - Enter BlockHash - - - Execution layer block hash of the proposed block with EL rewards - stealing - - - ); -}; diff --git a/features/stealing/stealing-report-form/controls/submit-button.tsx b/features/stealing/stealing-report-form/controls/submit-button.tsx deleted file mode 100644 index b148361b8..000000000 --- a/features/stealing/stealing-report-form/controls/submit-button.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { SubmitButtonHookForm } from 'shared/hook-form/controls'; - -export const SubmitButton = () => { - // TODO: disable - return ( - - Report stealing - - ); -}; diff --git a/features/stealing/stealing-report-form/hooks/use-tx-modal-stages-stealing-report.tsx b/features/stealing/stealing-report-form/hooks/use-tx-modal-stages-stealing-report.tsx deleted file mode 100644 index af3fd5845..000000000 --- a/features/stealing/stealing-report-form/hooks/use-tx-modal-stages-stealing-report.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import type { BigNumber } from 'ethers'; - -import { TOKENS } from 'consts/tokens'; -import { - TransactionModalTransitStage, - TxAmount, - TxStagePending, - TxStageSign, - TxStageSuccess, - getGeneralTransactionModalStages, - useTransactionModalStage, -} from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; - -type Props = { - amount: BigNumber; - nodeOperatorId: NodeOperatorId; - blockhash: string; -}; - -const getTxModalStagesStealingReport = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: ({ amount, nodeOperatorId }: Props) => - transitStage( - - Node Operator ID: {nodeOperatorId} -
          - Amount: - - } - />, - ), - - pending: ({ amount, nodeOperatorId }: Props, txHash?: string) => - transitStage( - - Node Operator ID: {nodeOperatorId} -
          - Amount: - - } - />, - ), - - success: ({ amount, nodeOperatorId }: Props, txHash?: string) => - transitStage( - - Node Operator ID: {nodeOperatorId} -
          - Amount: - - } - />, - { - isClosableOnLedger: true, - }, - ), -}); - -export const useTxModalStagesStealingReport = () => { - return useTransactionModalStage(getTxModalStagesStealingReport); -}; diff --git a/features/stealing/stealing-report-form/index.ts b/features/stealing/stealing-report-form/index.ts deleted file mode 100644 index 13688e99a..000000000 --- a/features/stealing/stealing-report-form/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { StealingReportForm } from './stealing-report-form'; diff --git a/features/stealing/stealing-report-form/stealing-report-form-loader.tsx b/features/stealing/stealing-report-form/stealing-report-form-loader.tsx deleted file mode 100644 index 67ee4bda5..000000000 --- a/features/stealing/stealing-report-form/stealing-report-form-loader.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { FC, PropsWithChildren } from 'react'; -import { useFormState } from 'react-hook-form'; -import { WhenLoaded } from 'shared/components'; -import { StealingReportFormInputType } from './context'; - -export const StealingReportFormLoader: FC = ({ - children, -}) => { - const { isLoading } = useFormState(); - - return {children}; -}; diff --git a/features/stealing/stealing-report-form/stealing-report-form.tsx b/features/stealing/stealing-report-form/stealing-report-form.tsx deleted file mode 100644 index 57fac9904..000000000 --- a/features/stealing/stealing-report-form/stealing-report-form.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { FC, memo } from 'react'; - -import { StealingReportFormProvider } from './context'; - -import { AmountInput } from './controls/amount-input'; -import { SubmitButton } from './controls/submit-button'; -import { FormBlock } from 'shared/components'; -import { FormControllerStyled } from 'shared/hook-form/form-controller'; -import { StealingReportFormLoader } from './stealing-report-form-loader'; -import { BlockhashInput } from './controls/blockhash-input'; -import { NodeOperatorInput } from './controls/node-operator-input'; - -export const StealingReportForm: FC = memo(() => { - return ( - - - - - - - - - - - - - ); -}); diff --git a/features/stealing/stealing-report-page.tsx b/features/stealing/stealing-report-page.tsx deleted file mode 100644 index 8765697e9..000000000 --- a/features/stealing/stealing-report-page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { FC } from 'react'; - -import { Layout } from 'shared/layout'; -import { StealingPageSwitcher } from 'shared/navigate'; -import { StealingReport } from './stealing-report'; - -export const StealingReportPage: FC = () => ( - - - - -); diff --git a/features/stealing/stealing-report.tsx b/features/stealing/stealing-report.tsx deleted file mode 100644 index 5cd36f133..000000000 --- a/features/stealing/stealing-report.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; - -import { StealingReportForm } from './stealing-report-form'; - -export const StealingReport = () => { - const key = useWeb3Key(); - return ( - <> - - - - - ); -}; diff --git a/features/surveys/components/survey-section.tsx b/features/surveys/components/survey-section.tsx index 45f3f109d..17158ca58 100644 --- a/features/surveys/components/survey-section.tsx +++ b/features/surveys/components/survey-section.tsx @@ -1,20 +1,23 @@ import { Text } from '@lidofinance/lido-ui'; -import { FC, PropsWithChildren } from 'react'; +import { FC, PropsWithChildren, ReactNode } from 'react'; import { IconTooltip, Stack } from 'shared/components'; type SurveySectionProps = { title: string; subtitle?: string; help?: string; + mainPrefix?: ReactNode; }; export const SurveySection: FC> = ({ children, title, subtitle, + mainPrefix, help, }) => { return ( + {mainPrefix} {title} diff --git a/features/surveys/index.ts b/features/surveys/index.ts index f82238e02..2fbc6444b 100644 --- a/features/surveys/index.ts +++ b/features/surveys/index.ts @@ -1,7 +1 @@ -export * from './surveys-contacts-page'; -export * from './surveys-experience-page'; -export * from './surveys-home-page'; -export * from './surveys-how-did-you-learn-page'; -export * from './surveys-setup-page'; -export * from './surveys-signin-page'; -export * from './shared'; +export * from './surveys-page'; diff --git a/features/surveys/shared/back-button.tsx b/features/surveys/shared/back-button.tsx index 53d1cdda7..0a6fdd90b 100644 --- a/features/surveys/shared/back-button.tsx +++ b/features/surveys/shared/back-button.tsx @@ -1,19 +1,7 @@ -import { ArrowLeft, ButtonIcon } from '@lidofinance/lido-ui'; import { PATH } from 'consts/urls'; import { FC } from 'react'; -import { LocalLink } from 'shared/navigate'; +import { BackButton as BackButtonBase } from 'shared/components'; -export const BackButton: FC = () => { - return ( - - } - > - Back - - - ); +export const SurveysBackButton: FC = () => { + return ; }; diff --git a/features/surveys/shared/gate-survey-auth.tsx b/features/surveys/shared/gate-survey-auth.tsx deleted file mode 100644 index a4c283056..000000000 --- a/features/surveys/shared/gate-survey-auth.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { FC, PropsWithChildren, ReactNode } from 'react'; -import { useAuth } from './survey-auth-provider'; - -type GateProps = { - fallback?: ReactNode; -}; - -export const GateSurveyAuth: FC> = ({ - fallback, - children, -}) => { - const { token } = useAuth(); - const canShow = !!token; - - return <>{canShow ? children : fallback}; -}; diff --git a/features/surveys/shared/index.ts b/features/surveys/shared/index.ts index cea5532de..1179aac07 100644 --- a/features/surveys/shared/index.ts +++ b/features/surveys/shared/index.ts @@ -1,5 +1 @@ export * from './back-button'; -export * from './gate-survey-auth'; -export * from './survey-auth-provider'; -export * from './use-siwe'; -export * from './use-surveys-fetcher'; diff --git a/features/surveys/shared/survey-auth-provider.tsx b/features/surveys/shared/survey-auth-provider.tsx deleted file mode 100644 index 915940450..000000000 --- a/features/surveys/shared/survey-auth-provider.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { useModalActions } from 'providers/modal-provider'; -import { - createContext, - FC, - PropsWithChildren, - useCallback, - useContext, - useMemo, -} from 'react'; -import { useAccount, useSessionStorage } from 'shared/hooks'; -import invariant from 'tiny-invariant'; -import { extractError } from 'utils'; -import { useModalStages } from './use-modal-stages'; -import { useSiwe } from './use-siwe'; -import { getExternalLinks } from 'consts/external-links'; - -type AuthContextType = { - token?: string; - signIn: () => Promise; - logout: () => void; -}; - -const AuthContext = createContext({} as AuthContextType); - -export const useAuth = () => { - const context = useContext(AuthContext); - invariant(context, 'Attempt to use `useAuth` outside of provider'); - return context; -}; - -const { surveyApi } = getExternalLinks(); - -export const SurveyAuthProvider: FC = ({ children }) => { - const siwe = useSiwe(); - const { address } = useAccount(); - const [token, setToken] = useSessionStorage( - `surveys-token-${address}`, - undefined, - ); - - const { txModalStages: modalStages } = useModalStages(); - const { closeModal } = useModalActions(); - - const signIn = useCallback(async () => { - modalStages.sign(); - - try { - const payload = await siwe(); - - modalStages.pending(); - const response = await fetch(`${surveyApi}/auth/signin`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(payload), - }); - if (!response.ok) { - modalStages.failed(await extractError(response)); - } - const data: { access_token: string; token_type: string } = - await response.json(); - setToken(`${data.token_type} ${data.access_token}`); - closeModal(); - } catch (e) { - modalStages.rejected(); - } - }, [closeModal, modalStages, setToken, siwe]); - - const logout = useCallback(() => { - setToken(undefined); - }, [setToken]); - - const value = useMemo( - () => ({ - token, - signIn, - logout, - }), - [logout, signIn, token], - ); - - return {children}; -}; diff --git a/features/surveys/shared/use-modal-stages.tsx b/features/surveys/shared/use-modal-stages.tsx deleted file mode 100644 index 1007966a4..000000000 --- a/features/surveys/shared/use-modal-stages.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { - TransactionModalTransitStage, - TxStageFail, - TxStagePending, - TxStagePermit, - useTransactionModalStage, -} from 'shared/transaction-modal'; -import { ErrorCode, getErrorCode } from 'utils'; - -const getModalStages = (transitStage: TransactionModalTransitStage) => ({ - sign: () => transitStage(), - - pending: () => - transitStage( - , - ), - - failed: (error: unknown) => - transitStage( - , - ), - - rejected: () => - transitStage( - , - ), -}); - -export const useModalStages = () => useTransactionModalStage(getModalStages); diff --git a/features/surveys/shared/use-siwe.ts b/features/surveys/shared/use-siwe.ts deleted file mode 100644 index 8409f15f0..000000000 --- a/features/surveys/shared/use-siwe.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { useSDK } from '@lido-sdk/react'; -import { addHours } from 'date-fns'; -import { useCallback } from 'react'; -import { SiweMessage } from 'siwe'; -import invariant from 'tiny-invariant'; - -const createSiweMessage = (address: string, chainId?: number) => { - const statement = 'Sign in to use the CSM Surveys'; - const scheme = window.location.protocol.slice(0, -1); - const domain = window.location.host; - const uri = window.location.origin; - - const message = new SiweMessage({ - scheme, - domain, - address, - statement, - uri, - version: '1', - chainId, - expirationTime: addHours(new Date(), 1).toISOString(), - }); - return message.prepareMessage(); -}; - -export const useSiwe = () => { - const { providerWeb3 } = useSDK(); - - return useCallback(async () => { - const signer = providerWeb3?.getSigner(); - invariant(signer, 'Signer is not available'); - - const message = createSiweMessage( - await signer.getAddress(), - await signer.getChainId(), - ); - - const signature = await signer.signMessage(message); - return { signature, message }; - }, [providerWeb3]); -}; diff --git a/features/surveys/shared/use-surveys-fetcher.ts b/features/surveys/shared/use-surveys-fetcher.ts deleted file mode 100644 index 66a31b752..000000000 --- a/features/surveys/shared/use-surveys-fetcher.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { useCallback } from 'react'; -import invariant from 'tiny-invariant'; -import { FetcherError, standardFetcher } from 'utils'; -import { useAuth } from './survey-auth-provider'; -import { getExternalLinks } from 'consts/external-links'; - -const { surveyApi } = getExternalLinks(); - -export const useSurveysFetcher = ( - transformIncoming?: (d: R) => T, - transformOutcoming?: (d: T) => R, -) => { - const { token, logout } = useAuth(); - - const handleError = useCallback( - (err: unknown) => { - const error = err as FetcherError; - if (error?.status === 401 || error.status === 403) { - logout(); - } - }, - [logout], - ); - - const fetcher = useCallback( - async (url: string) => { - invariant(token, 'Token is not available'); - try { - const res = await standardFetcher(`${surveyApi}/${url}`, { - headers: { - 'Content-type': 'application/json', - Authorization: token, - }, - }); - return res && transformIncoming ? transformIncoming(res) : (res as T); - } catch (err) { - handleError(err); - throw err; - } - }, - [handleError, token, transformIncoming], - ); - - const updater = useCallback( - (url: string, data: T | null) => async () => { - invariant(token, 'Token is not available'); - try { - const res = await standardFetcher(`${surveyApi}/${url}`, { - method: data === null ? 'DELETE' : 'POST', - body: JSON.stringify( - data && transformOutcoming ? transformOutcoming(data) : data, - ), - headers: { - 'Content-type': 'application/json', - Authorization: token, - }, - }); - return res && transformIncoming ? transformIncoming(res) : (res as T); - } catch (err) { - handleError(err); - throw err; - } - }, - [handleError, token, transformIncoming, transformOutcoming], - ); - - return [fetcher, updater] as const; -}; diff --git a/features/surveys/shared/use-surveys-swr.ts b/features/surveys/shared/use-surveys-swr.ts deleted file mode 100644 index 3d51c9a9e..000000000 --- a/features/surveys/shared/use-surveys-swr.ts +++ /dev/null @@ -1,55 +0,0 @@ -import useSWR from 'swr'; -import { useSurveysFetcher } from './use-surveys-fetcher'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { useCallback } from 'react'; -import { STRATEGY_LAZY } from 'consts/swr-strategies'; - -type Options = { - skipFetching?: boolean; - transformIncoming?: (d: R) => T; - transformOutcoming?: (d: T) => R; -}; - -export const useSurveysSWR = ( - path: string, - options?: Options, -) => { - const nodeOperatorId = useNodeOperatorId(); - const url = `csm-${nodeOperatorId}/${path}`; - - const [fetcher, updater] = useSurveysFetcher( - options?.transformIncoming, - options?.transformOutcoming, - ); - const swr = useSWR( - url, - options?.skipFetching ? null : fetcher, - STRATEGY_LAZY, - ); - - const mutate = useCallback( - (data?: T) => { - if (data === undefined) { - return swr.mutate(); - } - return swr.mutate(updater(url, data), { - rollbackOnError: true, - revalidate: false, - }); - }, - [swr, updater, url], - ); - - const remove = useCallback(() => { - return swr.mutate(updater(url, null), { - rollbackOnError: true, - revalidate: false, - }); - }, [swr, updater, url]); - - return { - ...swr, - mutate, - remove, - }; -}; diff --git a/features/surveys/siwe-sign-in/index.ts b/features/surveys/siwe-sign-in/index.ts index 6e79f6c72..b268590a8 100644 --- a/features/surveys/siwe-sign-in/index.ts +++ b/features/surveys/siwe-sign-in/index.ts @@ -1 +1,2 @@ +export * from './siwe-connect'; export * from './siwe-sign-in'; diff --git a/features/surveys/siwe-sign-in/siwe-connect.tsx b/features/surveys/siwe-sign-in/siwe-connect.tsx new file mode 100644 index 000000000..2536d71c6 --- /dev/null +++ b/features/surveys/siwe-sign-in/siwe-connect.tsx @@ -0,0 +1,21 @@ +import { FC } from 'react'; + +import { Text } from '@lidofinance/lido-ui'; +import { Block, Stack } from 'shared/components'; +import { Connect } from 'shared/wallet'; + +export const SiweConnect: FC = () => ( + + + + + Connect your wallet + + + Connect your wallet and sign a verification message to continue + + + + + +); diff --git a/features/surveys/siwe-sign-in/siwe-sign-in.tsx b/features/surveys/siwe-sign-in/siwe-sign-in.tsx index e38d11933..03243a692 100644 --- a/features/surveys/siwe-sign-in/siwe-sign-in.tsx +++ b/features/surveys/siwe-sign-in/siwe-sign-in.tsx @@ -1,14 +1,11 @@ import { Block, Button, Text } from '@lidofinance/lido-ui'; -import { FC, useCallback } from 'react'; +import { FC } from 'react'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; import { MatomoLink, Stack } from 'shared/components'; -import { useAuth } from '../shared'; +import { useSiweAuth } from 'modules/siwe'; export const SiweSignIn: FC = () => { - const { signIn } = useAuth(); - - const login = useCallback(() => { - void signIn(); - }, [signIn]); + const { signIn } = useSiweAuth(); return ( @@ -17,14 +14,18 @@ export const SiweSignIn: FC = () => { Here you can voluntarily provide information about your Node Operator, including your contact details, experience, and setup. This information may be used for report building ( - + VaNOM ), UI/UX improvements, or feedback purposes. To view or submit this information, you must sign in to verify that you are the owner of the - Reward or Manager address. + Reward or Manager Address. - diff --git a/features/surveys/survey-contacts/confirm-remove-modal.tsx b/features/surveys/survey-contacts/confirm-remove-modal.tsx index cc94d46e4..9d0da4e2d 100644 --- a/features/surveys/survey-contacts/confirm-remove-modal.tsx +++ b/features/surveys/survey-contacts/confirm-remove-modal.tsx @@ -17,7 +17,7 @@ export const ConfirmRemoveModal: ModalComponentType = ({ Are you sure you want to delete the provided contact information? - If deleted, the data will be permanently removed from the database. + If deleted, the data will be permanently removed from the database diff --git a/features/surveys/survey-contacts/survey-contacts.tsx b/features/surveys/survey-contacts/survey-contacts.tsx index 4f5ae2b4e..9ed205447 100644 --- a/features/surveys/survey-contacts/survey-contacts.tsx +++ b/features/surveys/survey-contacts/survey-contacts.tsx @@ -1,5 +1,6 @@ import { PATH } from 'consts/urls'; import { FC, useCallback } from 'react'; +import { trackMatomoFormEvent } from 'utils/track-matomo-event'; import { FormProvider, useForm } from 'react-hook-form'; import { FormTitle, SectionBlock, Stack, WhenLoaded } from 'shared/components'; import { @@ -8,15 +9,16 @@ import { TextInputHookForm, } from 'shared/hook-form/controls'; import { useNavigate } from 'shared/navigate'; +import { useOperatorSurvey } from 'modules/surveys-sdk'; import { SurveyButton } from '../components'; -import { useSurveysSWR } from '../shared/use-surveys-swr'; import { useConfirmRemoveModal } from './confirm-remove-modal'; import { useModalStages } from './use-modal-stages'; import { Text } from '@lidofinance/lido-ui'; import { Contact } from '../types'; +import { SurveysBackButton } from '../shared'; export const SurveyContacts: FC = () => { - const { data, mutate, remove } = useSurveysSWR('contacts'); + const { data, mutate, remove } = useOperatorSurvey('contacts'); const { txModalStages: modals } = useModalStages(); const confirmRemove = useConfirmRemoveModal(); const navigate = useNavigate(); @@ -30,9 +32,11 @@ export const SurveyContacts: FC = () => { const handleSubmit = useCallback( async (data: Contact) => { + trackMatomoFormEvent('surveyContacts'); modals.pending(); try { await mutate(data); + trackMatomoFormEvent('surveyContacts', 'success'); modals.success(); } catch (e) { modals.failed(e); @@ -55,7 +59,7 @@ export const SurveyContacts: FC = () => { }, [confirmRemove, modals, navigate, remove]); return ( - + }> diff --git a/features/surveys/survey-contacts/use-modal-stages.tsx b/features/surveys/survey-contacts/use-modal-stages.tsx index eadfd61bf..e8ede9b9a 100644 --- a/features/surveys/survey-contacts/use-modal-stages.tsx +++ b/features/surveys/survey-contacts/use-modal-stages.tsx @@ -5,7 +5,7 @@ import { TxStageSuccess, useTransactionModalStage, } from 'shared/transaction-modal'; -import { getErrorCode } from 'utils'; +import { extractErrorMessage, getErrorCode } from 'utils'; const getModalStages = (transitStage: TransactionModalTransitStage) => ({ pending: () => @@ -38,7 +38,11 @@ const getModalStages = (transitStage: TransactionModalTransitStage) => ({ failed: (error: unknown) => transitStage( - , + , ), }); diff --git a/features/surveys/survey-delegates/add-delegate-form.tsx b/features/surveys/survey-delegates/add-delegate-form.tsx new file mode 100644 index 000000000..03ae44e29 --- /dev/null +++ b/features/surveys/survey-delegates/add-delegate-form.tsx @@ -0,0 +1,65 @@ +import { FC, useCallback, useState } from 'react'; +import { useFormContext } from 'react-hook-form'; +import { isAddress } from 'viem'; +import { Stack } from 'shared/components'; +import { + AddressInputHookForm, + SubmitButtonHookForm, +} from 'shared/hook-form/controls'; + +type AddDelegateFormData = { + address: string; +}; + +type AddDelegateFormProps = { + onSubmit: (data: AddDelegateFormData) => void; + isSubmitting?: boolean; +}; + +export const AddDelegateForm: FC = ({ + onSubmit, + isSubmitting, +}) => { + const { handleSubmit, setError, clearErrors } = + useFormContext(); + const [validationError, setValidationError] = useState(); + + const handleFormSubmit = useCallback( + (data: AddDelegateFormData) => { + clearErrors('address'); + setValidationError(undefined); + + if (!data.address) { + setError('address', { type: 'manual', message: 'Address is required' }); + setValidationError('Address is required'); + return; + } + if (!isAddress(data.address)) { + setError('address', { + type: 'manual', + message: 'Invalid Ethereum address', + }); + setValidationError('Invalid Ethereum address'); + return; + } + onSubmit(data); + }, + [clearErrors, onSubmit, setError], + ); + + return ( +

          + + + + Add Delegate + + +
          + ); +}; diff --git a/features/surveys/survey-delegates/confirm-remove-modal.tsx b/features/surveys/survey-delegates/confirm-remove-modal.tsx new file mode 100644 index 000000000..a311d348c --- /dev/null +++ b/features/surveys/survey-delegates/confirm-remove-modal.tsx @@ -0,0 +1,39 @@ +import { Button, Modal, Text } from '@lidofinance/lido-ui'; +import type { ModalComponentType } from 'providers/modal-provider'; +import { Stack } from 'shared/components'; +import { ConfirmModalProps, getUseConfirmModal } from 'shared/hooks'; +import { Address } from 'shared/components/address'; + +type ConfirmRemoveDelegateProps = ConfirmModalProps & { + address: string; +}; + +export const ConfirmRemoveDelegateModal: ModalComponentType< + ConfirmRemoveDelegateProps +> = ({ onConfirm, onReject, address, ...props }) => { + return ( + + + + + Remove delegate? + + +
          will no longer have + delegate access + + + + + + + + + ); +}; + +export const useConfirmRemoveDelegateModal = getUseConfirmModal( + ConfirmRemoveDelegateModal, +); diff --git a/features/surveys/survey-delegates/delegate-item.tsx b/features/surveys/survey-delegates/delegate-item.tsx new file mode 100644 index 000000000..37dcb366e --- /dev/null +++ b/features/surveys/survey-delegates/delegate-item.tsx @@ -0,0 +1,32 @@ +import { FC } from 'react'; +import { Button } from '@lidofinance/lido-ui'; +import { Stack } from 'shared/components'; +import { Address } from 'shared/components/address'; +import { Delegate } from '../types'; + +type DelegateItemProps = { + delegate: Delegate; + onRemove: () => void; + isRemoving?: boolean; +}; + +export const DelegateItem: FC = ({ + delegate, + onRemove, + isRemoving, +}) => { + return ( + +
          + + + ); +}; diff --git a/features/surveys/survey-delegates/index.ts b/features/surveys/survey-delegates/index.ts new file mode 100644 index 000000000..407a6ffb4 --- /dev/null +++ b/features/surveys/survey-delegates/index.ts @@ -0,0 +1 @@ +export * from './survey-delegates'; diff --git a/features/surveys/survey-delegates/survey-delegates.tsx b/features/surveys/survey-delegates/survey-delegates.tsx new file mode 100644 index 000000000..5949665e6 --- /dev/null +++ b/features/surveys/survey-delegates/survey-delegates.tsx @@ -0,0 +1,110 @@ +import { FC, useCallback, useState } from 'react'; +import { trackMatomoFormEvent } from 'utils/track-matomo-event'; +import { FormProvider, useForm } from 'react-hook-form'; +import { Text } from '@lidofinance/lido-ui'; +import { Plural, SectionBlock, Stack, WhenLoaded } from 'shared/components'; +import { useDelegates } from './use-delegates'; +import { useModalStages } from './use-modal-stages'; +import { useConfirmRemoveDelegateModal } from './confirm-remove-modal'; +import { DelegateItem } from './delegate-item'; +import { AddDelegateForm } from './add-delegate-form'; +import { MAX_DELEGATES } from '../types'; +import { SurveysBackButton } from '../shared'; + +type AddDelegateFormData = { + address: string; +}; + +export const SurveyDelegates: FC = () => { + const { delegates, isLoading, add, remove, isAdding, canAddMore } = + useDelegates(); + const { txModalStages: modals } = useModalStages(); + const confirmRemove = useConfirmRemoveDelegateModal(); + const [removingAddress, setRemovingAddress] = useState(null); + + const formObject = useForm({ + defaultValues: { address: '' }, + }); + + const handleAdd = useCallback( + async (data: AddDelegateFormData) => { + trackMatomoFormEvent('surveyDelegates'); + modals.pending(); + try { + await add(data.address); + formObject.reset(); + trackMatomoFormEvent('surveyDelegates', 'success'); + modals.success(); + } catch (e) { + modals.failed(e); + } + }, + [add, formObject, modals], + ); + + const handleRemove = useCallback( + async (address: string) => { + if (await confirmRemove({ address })) { + setRemovingAddress(address); + modals.pendingRemove(); + try { + await remove(address); + modals.successRemove(); + } catch (e) { + modals.failed(e); + } finally { + setRemovingAddress(null); + } + } + }, + [confirmRemove, modals, remove], + ); + + return ( + }> + + + Delegates can only access and submit Setup surveys on your behalf. + Contact and experience data remains private. Up to{' '} + {' '} + allowed. + + + + + {delegates.map((delegate) => ( + handleRemove(delegate.address)} + isRemoving={removingAddress === delegate.address} + /> + ))} + + {delegates.length === 0 && ( + + No delegates added yet + + )} + + {canAddMore && ( + + + + )} + + {!canAddMore && ( + + Maximum number of delegates reached + + )} + + + + + ); +}; diff --git a/features/surveys/survey-delegates/use-delegates.ts b/features/surveys/survey-delegates/use-delegates.ts new file mode 100644 index 000000000..f1b5f05c7 --- /dev/null +++ b/features/surveys/survey-delegates/use-delegates.ts @@ -0,0 +1,80 @@ +import { + endpoints, + OperatorKey, + surveysKeys, + useOperatorKey, + useSurveysMutation, + useSurveysQuery, +} from 'modules/surveys-sdk'; +import { useCallback, useMemo } from 'react'; +import invariant from 'tiny-invariant'; +import { Delegate, DelegatesResponse, MAX_DELEGATES } from '../types'; + +export const useDelegates = () => { + const operatorKey = useOperatorKey(); + + const requireKey = useCallback((): OperatorKey => { + invariant(operatorKey, 'useDelegates: operator key is not available'); + return operatorKey; + }, [operatorKey]); + + const queryKey = useMemo( + () => + operatorKey + ? surveysKeys.path(operatorKey, 'delegates') + : surveysKeys.pending('delegates'), + [operatorKey], + ); + + const invalidate = useMemo( + () => + operatorKey ? [queryKey, surveysKeys.summary(operatorKey)] : [queryKey], + [operatorKey, queryKey], + ); + + const query = useSurveysQuery( + operatorKey ? endpoints.delegates(operatorKey) : '', + { + queryKey, + enabled: operatorKey !== undefined, + }, + ); + + const addMutation = useSurveysMutation( + () => endpoints.delegates(requireKey()), + { + mutationKey: ['surveys-delegates-add', operatorKey], + invalidate, + }, + ); + + const removeMutation = useSurveysMutation( + (address) => endpoints.delegate(requireKey(), address), + { + method: 'DELETE', + mutationKey: ['surveys-delegates-remove', operatorKey], + invalidate, + }, + ); + + const add = useCallback( + (address: string) => addMutation.mutateAsync({ address }), + [addMutation], + ); + + const remove = useCallback( + (address: string) => removeMutation.mutateAsync(address), + [removeMutation], + ); + + return { + delegates: query.data?.delegates ?? [], + isLoading: query.isLoading, + error: query.error, + add, + remove, + isAdding: addMutation.isPending, + isRemoving: removeMutation.isPending, + canAddMore: (query.data?.delegates?.length ?? 0) < MAX_DELEGATES, + }; +}; diff --git a/features/surveys/survey-delegates/use-modal-stages.tsx b/features/surveys/survey-delegates/use-modal-stages.tsx new file mode 100644 index 000000000..7d78dd9e4 --- /dev/null +++ b/features/surveys/survey-delegates/use-modal-stages.tsx @@ -0,0 +1,43 @@ +import { + TransactionModalTransitStage, + TxStageFail, + TxStagePending, + TxStageSuccess, + useTransactionModalStage, +} from 'shared/transaction-modal'; +import { extractErrorMessage, getErrorCode } from 'utils'; + +const getModalStages = (transitStage: TransactionModalTransitStage) => ({ + pending: () => + transitStage( + , + ), + + success: () => + transitStage(), + + pendingRemove: () => + transitStage( + , + ), + + successRemove: () => + transitStage(), + + failed: (error: unknown) => + transitStage( + , + ), +}); + +export const useModalStages = () => useTransactionModalStage(getModalStages); diff --git a/features/surveys/survey-delegator/back-button.tsx b/features/surveys/survey-delegator/back-button.tsx new file mode 100644 index 000000000..402bd4b7d --- /dev/null +++ b/features/surveys/survey-delegator/back-button.tsx @@ -0,0 +1,22 @@ +import { PATH } from 'consts/urls'; +import { FC } from 'react'; +import { BackButton } from 'shared/components'; +import { useSurveyContext } from '../surveys-provider'; + +type DelegatorBackButtonProps = { + operatorId?: string; +}; + +export const DelegatorBackButton: FC = ({ + operatorId, +}) => { + const { isOperator } = useSurveyContext(); + + const href = operatorId + ? (`${PATH.SURVEYS_DELEGATOR}/${operatorId}` as PATH) + : isOperator + ? PATH.SURVEYS_DELEGATOR + : PATH.SURVEYS; + + return ; +}; diff --git a/features/surveys/survey-delegator/delegator-home.tsx b/features/surveys/survey-delegator/delegator-home.tsx new file mode 100644 index 000000000..101e4ba03 --- /dev/null +++ b/features/surveys/survey-delegator/delegator-home.tsx @@ -0,0 +1,41 @@ +import { Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { FC } from 'react'; +import { Stack, WhenLoaded } from 'shared/components'; +import { SurveyItem, SurveyLink, SurveySection } from '../components'; +import { useSurveyContext } from '../surveys-provider'; +import { SurveysBackButton } from '../shared'; + +export const DelegatorHome: FC = () => { + const { delegatedOperators, isLoading } = useSurveyContext(); + + return ( + + } + > + {delegatedOperators?.length === 0 ? ( + + You are not a delegate for any node operator yet + + ) : ( + + {delegatedOperators?.map((operatorId) => ( + + + Manage setups + + + ))} + + )} + + + ); +}; diff --git a/features/surveys/survey-delegator/delegator-setup-form.tsx b/features/surveys/survey-delegator/delegator-setup-form.tsx new file mode 100644 index 000000000..0a0b6a176 --- /dev/null +++ b/features/surveys/survey-delegator/delegator-setup-form.tsx @@ -0,0 +1,332 @@ +import { FC, useCallback, useMemo } from 'react'; +import { trackMatomoFormEvent } from 'utils/track-matomo-event'; +import { FormProvider, useForm } from 'react-hook-form'; +import { + FormTitle, + Plural, + SectionBlock, + Stack, + WhenLoaded, +} from 'shared/components'; +import { + CheckboxHookForm, + NumberInputHookForm, + SelectHookForm, + SubmitButtonHookForm, + TokenAmountInputHookForm, +} from 'shared/hook-form/controls'; +import { parseOperatorKey, useOperatorSurvey } from 'modules/surveys-sdk'; +import { + CL_CLIENT_OPTIONS, + COUNTRY_OPTIONS, + DVT_OPTIONS, + EL_CLIENT_OPTIONS, + REMOTE_SIGNER_OPTIONS, + SERVER_TYPE_OPTIONS, + TOOL_OPTIONS, + VALIDATOR_CLIENT_OPTIONS, +} from '../survey-setup/options'; +import { + transformIncoming, + transformOutgoing, +} from '../survey-setup/transform'; +import { useModalStages } from '../survey-setup/use-modal-stages'; +import { useConfirmRemoveModal } from '../survey-setup/confirm-remove-modal'; +import { useNavigate } from 'shared/navigate'; +import { PATH } from 'consts/urls'; +import { SurveyButton } from '../components'; +import { Button } from '@lidofinance/lido-ui'; +import { Setup, SetupRaw, SetupsKeys } from '../types'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { DelegatorBackButton } from './back-button'; + +const required = { required: true }; + +type DelegatorSetupFormProps = { + operatorId: string; + setupId?: string; +}; + +export const DelegatorSetupForm: FC = ({ + operatorId, + setupId, +}) => { + const isEditMode = !!setupId && setupId !== 'new'; + const operatorKey = parseOperatorKey(operatorId) ?? undefined; + + const { + data: filled, + error, + mutate, + remove, + } = useOperatorSurvey( + `setups${isEditMode ? '/' + setupId : ''}`, + { + operatorKey, + skipFetching: !isEditMode, + invalidateOnMutate: true, + transformIncoming, + transformOutgoing, + }, + ); + + const data = useMemo( + () => (isEditMode ? filled : undefined), + [isEditMode, filled], + ); + + const { data: keys, mutate: mutateKeys } = useOperatorSurvey( + 'setups/keys', + { operatorKey }, + ); + + const filledWitoutCurrent = Math.max( + 0, + (keys?.filled ?? 0) - (data?.keysCount ?? 0), + ); + const keysLeft = Math.max(0, (keys?.total ?? 0) - filledWitoutCurrent); + + const maxKeys = Math.max(keysLeft, data?.keysCount ?? 0); + + const { txModalStages: modals } = useModalStages(); + const confirmRemove = useConfirmRemoveModal(); + const navigate = useNavigate(); + + const formObject = useForm({ + values: isEditMode ? data : undefined, + defaultValues: { + validatorSameAsCl: true, + }, + }); + + const validatorSameAsCl = formObject.watch('validatorSameAsCl'); + const keysCount = formObject.watch('keysCount'); + const keysRemain = Math.max(0, keysLeft - (keysCount ?? 0)); + + const handleSubmit = useCallback( + async (data: Setup) => { + trackMatomoFormEvent('surveyDelegatorSetup'); + modals.pending(); + try { + const res = await mutate(data); + void mutateKeys(); + if (!isEditMode && res?.index) { + void navigate( + `${PATH.SURVEYS_DELEGATOR}/${operatorId}/${res.index}` as PATH, + ); + } + trackMatomoFormEvent('surveyDelegatorSetup', 'success'); + modals.success(); + } catch (e) { + modals.failed(e); + } + }, + [modals, mutate, mutateKeys, isEditMode, navigate, operatorId], + ); + + const handleRemove = useCallback(async () => { + if (await confirmRemove({})) { + modals.pendingRemove(); + try { + await remove(); + void mutateKeys(); + void navigate(`${PATH.SURVEYS_DELEGATOR}/${operatorId}` as PATH); + modals.successRemove(); + } catch (e) { + modals.failed(e); + } + } + }, [confirmRemove, modals, mutateKeys, navigate, remove, operatorId]); + + const onKeysClick = useCallback(() => { + formObject.setValue('keysCount', keysLeft); + }, [formObject, keysLeft]); + + return ( + } + > + + + +
          + + + Number of keys in this setup + + {keysRemain}{' '} + {' '} + left + + ) + } + /> + + + + + Are you using Distributed Validator Technology to run these + validators? + + + + + + + Which tool do you use to run your nodes/keys? + + + + + + + Which Execution Layer Client are you running? + + + + + + + Which Consensus Layer Client are you running? + + + + + + + What type of servers are your EL and CL nodes running on? + + + + + + + Which country are your EL and CL nodes in? + + + + + + Which Validator Client are you running? + + {!validatorSameAsCl && ( + + )} + + + {!validatorSameAsCl && ( + + + What type of servers are your Validator Clients running + on? + + + + )} + + {!validatorSameAsCl && ( + + + Which country are your Validator Clients in? + + + + )} + + + + Do you use a remote signer for your validator keys? + + + + + + What is your MEV-boost min-bid value? + + + Submit + +
          + {!!data && ( + + )} +
          +
          +
          +
          + ); +}; diff --git a/features/surveys/survey-delegator/delegator-setups.tsx b/features/surveys/survey-delegator/delegator-setups.tsx new file mode 100644 index 000000000..a1d883b19 --- /dev/null +++ b/features/surveys/survey-delegator/delegator-setups.tsx @@ -0,0 +1,99 @@ +import { Plus, Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { FC } from 'react'; +import { Plural, Stack, WhenLoaded } from 'shared/components'; +import { formatDaysAgo } from 'utils'; +import { SurveyItem, SurveyLink, SurveySection, Warning } from '../components'; +import { parseOperatorKey, useOperatorSurvey } from 'modules/surveys-sdk'; +import { SetupRaw, SetupsKeys } from '../types'; +import { DelegatorBackButton } from './back-button'; + +type DelegatorSetupsProps = { + operatorId: string; +}; + +export const DelegatorSetups: FC = ({ operatorId }) => { + const operatorKey = parseOperatorKey(operatorId) ?? undefined; + + const { data, isLoading } = useOperatorSurvey('setups', { + operatorKey, + }); + const { data: keys } = useOperatorSurvey('setups/keys', { + operatorKey, + }); + + const showSetups = !!(keys && (keys.total > 0 || keys.filled > 0)); + + return ( + + } + > + {!showSetups ? ( + + No keys available for this operator + + ) : ( + <> + {keys && keys.filled > keys.total && ( + + The number of keys has decreased. Please update the data. + + )} + {data?.map((setup) => ( + + + Setup #{setup.index}{' '} + + {setup.keysCount}{' '} + + + + + Updated {formatDaysAgo(setup.updatedAt)} + + + } + > + + Edit + + + ))} + + {keys && keys.left > 0 && ( + } + color="primary" + variant="translucent" + fullwidth + path={`${PATH.SURVEYS_DELEGATOR}/${operatorId}/new`} + > + <> + Add new setup + <> + {' '} + ({keys.left}{' '} + {' '} + left) + + + + )} + + )} + + + ); +}; diff --git a/features/surveys/survey-delegator/index.ts b/features/surveys/survey-delegator/index.ts new file mode 100644 index 000000000..3d78fc7f7 --- /dev/null +++ b/features/surveys/survey-delegator/index.ts @@ -0,0 +1,4 @@ +export { DelegatorBackButton } from './back-button'; +export { DelegatorHome } from './delegator-home'; +export { DelegatorSetups } from './delegator-setups'; +export { DelegatorSetupForm } from './delegator-setup-form'; diff --git a/features/surveys/survey-experience/survey-experience.tsx b/features/surveys/survey-experience/survey-experience.tsx index bf38b73b0..4ec5f9c37 100644 --- a/features/surveys/survey-experience/survey-experience.tsx +++ b/features/surveys/survey-experience/survey-experience.tsx @@ -1,4 +1,5 @@ import { FC, useCallback } from 'react'; +import { trackMatomoFormEvent } from 'utils/track-matomo-event'; import { FormProvider, useForm } from 'react-hook-form'; import { FormTitle, SectionBlock, Stack, WhenLoaded } from 'shared/components'; import { @@ -7,21 +8,22 @@ import { SubmitButtonHookForm, TextInputHookForm, } from 'shared/hook-form/controls'; -import { useSurveysSWR } from '../shared/use-surveys-swr'; +import { useOperatorSurvey } from 'modules/surveys-sdk'; import { Experience } from '../types'; import { ExperienceForm, transformIncoming, - transformOutcoming, + transformOutgoing, } from './transform'; import { useModalStages } from './use-modal-stages'; +import { SurveysBackButton } from '../shared'; export const SurveyExperience: FC = () => { - const { data, mutate } = useSurveysSWR( + const { data, mutate } = useOperatorSurvey( 'experience', { transformIncoming, - transformOutcoming, + transformOutgoing, }, ); const { txModalStages: modals } = useModalStages(); @@ -34,9 +36,11 @@ export const SurveyExperience: FC = () => { const handleSubmit = useCallback( async (data: ExperienceForm) => { + trackMatomoFormEvent('surveyExperience'); modals.pending(); try { await mutate(data); + trackMatomoFormEvent('surveyExperience', 'success'); modals.success(); } catch (e) { modals.failed(e); @@ -46,7 +50,10 @@ export const SurveyExperience: FC = () => { ); return ( - + } + > diff --git a/features/surveys/survey-experience/transform.tsx b/features/surveys/survey-experience/transform.tsx index 78a7e5cf1..f77dad683 100644 --- a/features/surveys/survey-experience/transform.tsx +++ b/features/surveys/survey-experience/transform.tsx @@ -9,7 +9,7 @@ export type ExperienceForm = { otherValidatorsCount: number; }; -export const transformOutcoming = (data: ExperienceForm): Experience => ({ +export const transformOutgoing = (data: ExperienceForm): Experience => ({ professional: data.professional === 'on', validatedBefore: data.validatedBefore === 'on', fromCurated: diff --git a/features/surveys/survey-experience/use-modal-stages.tsx b/features/surveys/survey-experience/use-modal-stages.tsx index 31f13dd8a..622444a03 100644 --- a/features/surveys/survey-experience/use-modal-stages.tsx +++ b/features/surveys/survey-experience/use-modal-stages.tsx @@ -5,7 +5,7 @@ import { TxStageSuccess, useTransactionModalStage, } from 'shared/transaction-modal'; -import { getErrorCode } from 'utils'; +import { extractErrorMessage, getErrorCode } from 'utils'; const getModalStages = (transitStage: TransactionModalTransitStage) => ({ pending: () => @@ -26,7 +26,11 @@ const getModalStages = (transitStage: TransactionModalTransitStage) => ({ failed: (error: unknown) => transitStage( - , + , ), }); diff --git a/features/surveys/survey-how-did-you-learn-csm/survey-how-did-you-learn-csm.tsx b/features/surveys/survey-how-did-you-learn-csm/survey-how-did-you-learn-csm.tsx index 05cb64c4e..772428493 100644 --- a/features/surveys/survey-how-did-you-learn-csm/survey-how-did-you-learn-csm.tsx +++ b/features/surveys/survey-how-did-you-learn-csm/survey-how-did-you-learn-csm.tsx @@ -1,4 +1,5 @@ import { FC, useCallback, useEffect } from 'react'; +import { trackMatomoFormEvent } from 'utils/track-matomo-event'; import { FormProvider, useForm } from 'react-hook-form'; import { FormTitle, SectionBlock, Stack, WhenLoaded } from 'shared/components'; import { @@ -6,16 +7,17 @@ import { SubmitButtonHookForm, TextInputHookForm, } from 'shared/hook-form/controls'; -import { useSurveysSWR } from '../shared/use-surveys-swr'; +import { useOperatorSurvey } from 'modules/surveys-sdk'; import { HowDidYouLearnCsm } from '../types'; import { useModalStages } from './use-modal-stages'; import { sources } from './sources'; -import { transformOutcoming } from './transform'; +import { transformOutgoing } from './transform'; +import { SurveysBackButton } from '../shared'; export const SurveyHowDidYouLearnCsm: FC = () => { - const { data, mutate } = useSurveysSWR( + const { data, mutate } = useOperatorSurvey( 'how-did-you-learn-csm', - { transformOutcoming }, + { transformOutgoing }, ); const { txModalStages: modals } = useModalStages(); @@ -25,9 +27,11 @@ export const SurveyHowDidYouLearnCsm: FC = () => { const handleSubmit = useCallback( async (data: HowDidYouLearnCsm) => { + trackMatomoFormEvent('surveyLearnCsm'); modals.pending(); try { await mutate(data); + trackMatomoFormEvent('surveyLearnCsm', 'success'); modals.success(); } catch (e) { modals.failed(e); @@ -49,7 +53,10 @@ export const SurveyHowDidYouLearnCsm: FC = () => { }, [formObject, sourceOne, sourceTwo]); return ( - + } + > diff --git a/features/surveys/survey-how-did-you-learn-csm/transform.tsx b/features/surveys/survey-how-did-you-learn-csm/transform.tsx index 1e14544f1..6dcf69562 100644 --- a/features/surveys/survey-how-did-you-learn-csm/transform.tsx +++ b/features/surveys/survey-how-did-you-learn-csm/transform.tsx @@ -1,6 +1,6 @@ import { HowDidYouLearnCsm } from '../types'; -export const transformOutcoming = ( +export const transformOutgoing = ( data: HowDidYouLearnCsm, ): HowDidYouLearnCsm => ({ ...data, diff --git a/features/surveys/survey-how-did-you-learn-csm/use-modal-stages.tsx b/features/surveys/survey-how-did-you-learn-csm/use-modal-stages.tsx index 4a29a0d7b..f4c226377 100644 --- a/features/surveys/survey-how-did-you-learn-csm/use-modal-stages.tsx +++ b/features/surveys/survey-how-did-you-learn-csm/use-modal-stages.tsx @@ -5,7 +5,7 @@ import { TxStageSuccess, useTransactionModalStage, } from 'shared/transaction-modal'; -import { getErrorCode } from 'utils'; +import { extractErrorMessage, getErrorCode } from 'utils'; const getModalStages = (transitStage: TransactionModalTransitStage) => ({ pending: () => @@ -21,7 +21,11 @@ const getModalStages = (transitStage: TransactionModalTransitStage) => ({ failed: (error: unknown) => transitStage( - , + , ), }); diff --git a/features/surveys/survey-setup/confirm-remove-modal.tsx b/features/surveys/survey-setup/confirm-remove-modal.tsx index c4b0b6066..d28878825 100644 --- a/features/surveys/survey-setup/confirm-remove-modal.tsx +++ b/features/surveys/survey-setup/confirm-remove-modal.tsx @@ -17,7 +17,7 @@ export const ConfirmRemoveModal: ModalComponentType = ({ Are you sure you want to delete filled contact info? - If the data is deleted, it will be deleted from the database. + If the data is deleted, it will be deleted from the database diff --git a/features/surveys/survey-setup/survey-setup.tsx b/features/surveys/survey-setup/survey-setup.tsx index 9def91de3..a5f0c8dca 100644 --- a/features/surveys/survey-setup/survey-setup.tsx +++ b/features/surveys/survey-setup/survey-setup.tsx @@ -1,4 +1,5 @@ import { FC, useCallback, useMemo } from 'react'; +import { trackMatomoFormEvent } from 'utils/track-matomo-event'; import { FormProvider, useForm } from 'react-hook-form'; import { FormTitle, @@ -14,7 +15,7 @@ import { SubmitButtonHookForm, TokenAmountInputHookForm, } from 'shared/hook-form/controls'; -import { useSurveysSWR } from '../shared/use-surveys-swr'; +import { useOperatorSurvey } from 'modules/surveys-sdk'; import { CL_CLIENT_OPTIONS, COUNTRY_OPTIONS, @@ -25,7 +26,7 @@ import { TOOL_OPTIONS, VALIDATOR_CLIENT_OPTIONS, } from './options'; -import { transformIncoming, transformOutcoming } from './transform'; +import { transformIncoming, transformOutgoing } from './transform'; import { useModalStages } from './use-modal-stages'; import { useConfirmRemoveModal } from './confirm-remove-modal'; import { useNavigate } from 'shared/navigate'; @@ -33,6 +34,10 @@ import { PATH } from 'consts/urls'; import { SurveyButton } from '../components'; import { Button } from '@lidofinance/lido-ui'; import { Setup, SetupRaw, SetupsKeys } from '../types'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { useSurveysFilled } from 'shared/hooks'; +import { useNodeOperatorId } from 'modules/web3'; +import { SurveysBackButton } from '../shared'; const required = { required: true }; @@ -42,16 +47,19 @@ export const SurveySetup: FC<{ id?: string }> = ({ id }) => { error, mutate, remove, - } = useSurveysSWR(`setups${id ? '/' + id : ''}`, { + } = useOperatorSurvey(`setups${id ? '/' + id : ''}`, { skipFetching: !id, transformIncoming, - transformOutcoming, + transformOutgoing, }); const data = useMemo(() => (id ? filled : undefined), [id, filled]); const { data: keys, mutate: mutateKeys } = - useSurveysSWR('setups/keys'); + useOperatorSurvey('setups/keys'); + + const nodeOperatorId = useNodeOperatorId(); + const { refetch } = useSurveysFilled(nodeOperatorId); const filledWitoutCurrent = Math.max( 0, @@ -78,19 +86,22 @@ export const SurveySetup: FC<{ id?: string }> = ({ id }) => { const handleSubmit = useCallback( async (data: Setup) => { + trackMatomoFormEvent('surveySetup'); modals.pending(); try { const res = await mutate(data); void mutateKeys(); + void refetch(); if (!id && res?.index) { void navigate(`${PATH.SURVEYS_SETUP}/${res.index}` as PATH); } + trackMatomoFormEvent('surveySetup', 'success'); modals.success(); } catch (e) { modals.failed(e); } }, - [modals, mutate, id, mutateKeys, navigate], + [modals, mutate, mutateKeys, refetch, id, navigate], ); const handleRemove = useCallback(async () => { @@ -112,7 +123,10 @@ export const SurveySetup: FC<{ id?: string }> = ({ id }) => { }, [formObject, keysLeft]); return ( - + } + > @@ -216,7 +230,6 @@ export const SurveySetup: FC<{ id?: string }> = ({ id }) => { @@ -257,7 +270,6 @@ export const SurveySetup: FC<{ id?: string }> = ({ id }) => { )} @@ -278,8 +290,7 @@ export const SurveySetup: FC<{ id?: string }> = ({ id }) => { Submit diff --git a/features/surveys/survey-setup/transform.tsx b/features/surveys/survey-setup/transform.tsx index 0c0d593cb..933ae74cd 100644 --- a/features/surveys/survey-setup/transform.tsx +++ b/features/surveys/survey-setup/transform.tsx @@ -1,15 +1,14 @@ -import { BigNumber } from 'ethers'; import { Setup, SetupRaw } from '../types'; -export const transformOutcoming = (data: Setup): SetupRaw => ({ +export const transformOutgoing = (data: Setup): SetupRaw => ({ ...data, - mevMinBid: data.mevMinBid?.toString(), + mevMinBid: data.mevMinBid?.toString() || null, validatorClient: data.validatorSameAsCl ? '' : data.validatorClient, validatorServerType: data.validatorSameAsCl ? '' : data.validatorServerType, validatorCountry: data.validatorSameAsCl ? '' : data.validatorCountry, }); export const transformIncoming = (data: SetupRaw): Setup => ({ ...data, - mevMinBid: BigNumber.from(data.mevMinBid), + mevMinBid: data.mevMinBid ? BigInt(data.mevMinBid) : undefined, validatorSameAsCl: data.validatorSameAsCl ?? false, }); diff --git a/features/surveys/survey-setup/use-modal-stages.tsx b/features/surveys/survey-setup/use-modal-stages.tsx index 7ba4368a6..1aa8c3571 100644 --- a/features/surveys/survey-setup/use-modal-stages.tsx +++ b/features/surveys/survey-setup/use-modal-stages.tsx @@ -5,7 +5,7 @@ import { TxStageSuccess, useTransactionModalStage, } from 'shared/transaction-modal'; -import { getErrorCode } from 'utils'; +import { extractErrorMessage, getErrorCode } from 'utils'; const getModalStages = (transitStage: TransactionModalTransitStage) => ({ pending: () => @@ -31,7 +31,11 @@ const getModalStages = (transitStage: TransactionModalTransitStage) => ({ failed: (error: unknown) => transitStage( - , + , ), }); diff --git a/features/surveys/surveys-contacts-page.tsx b/features/surveys/surveys-contacts-page.tsx index 8e087bcad..d189afca8 100644 --- a/features/surveys/surveys-contacts-page.tsx +++ b/features/surveys/surveys-contacts-page.tsx @@ -1,15 +1,10 @@ import { FC } from 'react'; -import { NoSSRWrapper } from 'shared/components'; -import { Layout } from 'shared/layout'; import { SurveyContacts } from './survey-contacts'; -import { BackButton } from './shared'; +import { SurveyOperatorGate } from './surveys-provider'; export const SurveysContactsPage: FC = () => ( - - - - - - + + + ); diff --git a/features/surveys/surveys-delegates-page.tsx b/features/surveys/surveys-delegates-page.tsx new file mode 100644 index 000000000..f0f585c2b --- /dev/null +++ b/features/surveys/surveys-delegates-page.tsx @@ -0,0 +1,10 @@ +import { FC } from 'react'; + +import { SurveyDelegates } from './survey-delegates'; +import { SurveyOperatorGate } from './surveys-provider'; + +export const SurveysDelegatesPage: FC = () => ( + + + +); diff --git a/features/surveys/surveys-delegator-page.tsx b/features/surveys/surveys-delegator-page.tsx new file mode 100644 index 000000000..87cdc14b1 --- /dev/null +++ b/features/surveys/surveys-delegator-page.tsx @@ -0,0 +1,43 @@ +import { FC } from 'react'; +import { NoSSRWrapper } from 'shared/components'; +import { + DelegatorHome, + DelegatorSetupForm, + DelegatorSetups, +} from './survey-delegator'; +import { SurveyDelegatorGate } from './surveys-provider'; + +type SurveysDelegatorPageProps = { + operatorId?: string; + setupId?: string; +}; + +export const SurveysDelegatorPage: FC = ({ + operatorId, + setupId, +}) => { + // No operatorId means we're at the delegator home page (accessible to all) + if (!operatorId) { + return ( + + + + ); + } + + // operatorId but no setupId means we're viewing setups for an operator + if (!setupId) { + return ( + + + + ); + } + + // Both operatorId and setupId means we're editing/adding a setup + return ( + + + + ); +}; diff --git a/features/surveys/surveys-experience-page.tsx b/features/surveys/surveys-experience-page.tsx index 6faf8d8c1..a9e0fc601 100644 --- a/features/surveys/surveys-experience-page.tsx +++ b/features/surveys/surveys-experience-page.tsx @@ -1,15 +1,10 @@ import { FC } from 'react'; -import { NoSSRWrapper } from 'shared/components'; -import { Layout } from 'shared/layout'; -import { BackButton } from './shared'; import { SurveyExperience } from './survey-experience'; +import { SurveyOperatorGate } from './surveys-provider'; export const SurveysExperiencePage: FC = () => ( - - - - - - + + + ); diff --git a/features/surveys/surveys-home-page.tsx b/features/surveys/surveys-home-page.tsx index 09ddb1970..336f2bb7f 100644 --- a/features/surveys/surveys-home-page.tsx +++ b/features/surveys/surveys-home-page.tsx @@ -1,13 +1,5 @@ import { FC } from 'react'; -import { NoSSRWrapper } from 'shared/components'; -import { Layout } from 'shared/layout'; import { SurveysHome } from './surveys-home/surverys-home'; -export const SurveysHomePage: FC = () => ( - - - - - -); +export const SurveysHomePage: FC = () => ; diff --git a/features/surveys/surveys-home/confirm-erase-modal.tsx b/features/surveys/surveys-home/confirm-erase-modal.tsx index 718e1d9eb..18e71fc10 100644 --- a/features/surveys/surveys-home/confirm-erase-modal.tsx +++ b/features/surveys/surveys-home/confirm-erase-modal.tsx @@ -9,15 +9,7 @@ export const ConfirmEraseModal: ModalComponentType = ({ ...props }) => { return ( - - // Are you sure you want to erase your data from the database? - // - // } - onClose={onReject} - > + @@ -26,7 +18,7 @@ export const ConfirmEraseModal: ModalComponentType = ({ If the data is erased, it will be deleted from the database; however, the historic usage of the data for the compilation of - aggregate statistics will remain in the previous VaNOM reports. + aggregate statistics will remain in the previous VaNOM reports diff --git a/features/surveys/surveys-home/surverys-home.tsx b/features/surveys/surveys-home/surverys-home.tsx index 21e5f9c05..220b85d89 100644 --- a/features/surveys/surveys-home/surverys-home.tsx +++ b/features/surveys/surveys-home/surverys-home.tsx @@ -1,143 +1,19 @@ -import { PATH } from 'consts/urls'; -import { FC, useCallback } from 'react'; -import { Plural, Stack, WhenLoaded } from 'shared/components'; -import { - SurveyLink, - SurveyItem, - SurveySection, - SurveyButton, - Warning, -} from '../components'; -import { useSurveysSWR } from '../shared/use-surveys-swr'; -import { useConfirmEraseModal } from './confirm-erase-modal'; -import { Divider, Plus, Text } from '@lidofinance/lido-ui'; -import { SetupsKeys, Summary } from '../types'; +import { FC } from 'react'; +import { WhenLoaded } from 'shared/components'; +import { DelegatorHome } from '../survey-delegator'; +import { useSurveyContext } from '../surveys-provider'; +import { SurveysOperatorHome } from './surverys-operator-home'; +import { SurveysEmpty } from './surveys-empty'; export const SurveysHome: FC = () => { - const { data, isLoading, remove } = useSurveysSWR('summary'); - const { data: keys, mutate: mutateKeys } = - useSurveysSWR('setups/keys'); - - const confirmModal = useConfirmEraseModal(); - - const handleErase = useCallback(async () => { - if (await confirmModal({})) { - await remove(); - void mutateKeys(); - } - }, [confirmModal, mutateKeys, remove]); + const { mode, isLoading } = useSurveyContext(); return ( - - - - - {data?.contacts ? 'Filled' : 'Fill in'} - - - - - - - - {data?.howDidYouLearnCsm ? 'Filled' : 'Fill in'} - - - - - {data?.experience ? 'Filled' : 'Fill in'} - - - - - {keys && (keys.total > 0 || keys.filled > 0) && ( - - {keys && keys.filled > keys.total && ( - - The number of your keys has decreased. Please update the data - - )} - {data?.setups.map((setup) => ( - - Setup #{setup.index}{' '} - - {setup.keysCount}{' '} - - - - } - > - - Edit - - - ))} - - {keys && keys.left > 0 && ( - } - color="primary" - variant="translucent" - fullwidth - path={PATH.SURVEYS_SETUP} - > - <> - Add new setup - <> - {' '} - ({keys.left}{' '} - left) - - - - )} - - )} - - {(data?.contacts || - data?.experience || - data?.howDidYouLearnCsm || - (data?.setups && data.setups.length > 0)) && ( - <> - - - - - - )} + } + > + {mode.type === 'delegator' ? : } ); }; diff --git a/features/surveys/surveys-home/surverys-operator-home.tsx b/features/surveys/surveys-home/surverys-operator-home.tsx new file mode 100644 index 000000000..05da56f80 --- /dev/null +++ b/features/surveys/surveys-home/surverys-operator-home.tsx @@ -0,0 +1,200 @@ +import { Divider, Plus, Text } from '@lidofinance/lido-ui'; +import { PATH } from 'consts/urls'; +import { FC, useCallback } from 'react'; +import { Plural, Stack, WhenLoaded } from 'shared/components'; +import { formatDaysAgo, plural } from 'utils'; +import { useOperatorSurvey } from 'modules/surveys-sdk'; +import { + SurveyButton, + SurveyItem, + SurveyLink, + SurveySection, + Warning, +} from '../components'; +import { useSurveyContext } from '../surveys-provider'; +import { MAX_DELEGATES, SetupsKeys, Summary } from '../types'; +import { useConfirmEraseModal } from './confirm-erase-modal'; + +export const SurveysOperatorHome: FC = () => { + const { data, isLoading, remove } = useOperatorSurvey('summary'); + const { data: keys, mutate: mutateKeys } = + useOperatorSurvey('setups/keys'); + const { delegatedOperators } = useSurveyContext(); + + const confirmModal = useConfirmEraseModal(); + + const handleErase = useCallback(async () => { + if (await confirmModal({})) { + await remove(); + void mutateKeys(); + } + }, [confirmModal, mutateKeys, remove]); + + const showErase = !!( + data?.contacts || + data?.experience || + data?.howDidYouLearnCsm || + (data?.setups && data.setups.length > 0) + ); + const showSetups = !!(keys && (keys.total > 0 || keys.filled > 0)); + + return ( + + + + + {data?.contacts ? 'Filled' : 'Fill in'} + + + + + + + + {data?.howDidYouLearnCsm ? 'Filled' : 'Fill in'} + + + + + {data?.experience ? 'Filled' : 'Fill in'} + + + + + {showSetups && ( + + {keys && keys.filled > keys.total && ( + + The number of your keys has decreased. Please update the data. + + )} + {data?.setups.map((setup) => ( + + + Setup #{setup.index}{' '} + + {setup.keysCount}{' '} + + + + + Updated {formatDaysAgo(setup.updatedAt)} + + + } + > + + Edit + + + ))} + + {keys && keys.left > 0 && ( + } + color="primary" + variant="translucent" + fullwidth + path={PATH.SURVEYS_SETUP} + > + <> + Add new setup + <> + {' '} + ({keys.left}{' '} + left) + + + + )} + + )} + + + + Delegates + + {data?.delegates.length} + + + } + > + Manage + + + + {showErase && ( + <> + + + + + + )} + + {delegatedOperators.length > 0 && ( + <> + + + + Operators + + {delegatedOperators.length} + + + } + > + Manage + + + + )} + + ); +}; diff --git a/features/surveys/surveys-home/surveys-empty.tsx b/features/surveys/surveys-home/surveys-empty.tsx new file mode 100644 index 000000000..af92921be --- /dev/null +++ b/features/surveys/surveys-home/surveys-empty.tsx @@ -0,0 +1,12 @@ +import { FC } from 'react'; +import { SurveySection } from '../components'; +import { Text } from '@lidofinance/lido-ui'; + +export const SurveysEmpty: FC = () => ( + + + You are not a node operator and have not been added as a delegate for any + operators + + +); diff --git a/features/surveys/surveys-how-did-you-learn-page.tsx b/features/surveys/surveys-how-did-you-learn-page.tsx index 5f1de9dd7..d23207708 100644 --- a/features/surveys/surveys-how-did-you-learn-page.tsx +++ b/features/surveys/surveys-how-did-you-learn-page.tsx @@ -1,15 +1,10 @@ import { FC } from 'react'; -import { NoSSRWrapper } from 'shared/components'; -import { Layout } from 'shared/layout'; -import { BackButton } from './shared'; import { SurveyHowDidYouLearnCsm } from './survey-how-did-you-learn-csm'; +import { SurveyOperatorGate } from './surveys-provider'; export const SurveysHowDidYouLearnCsmPage: FC = () => ( - - - - - - + + + ); diff --git a/features/surveys/surveys-page.tsx b/features/surveys/surveys-page.tsx new file mode 100644 index 000000000..c61b9b4a7 --- /dev/null +++ b/features/surveys/surveys-page.tsx @@ -0,0 +1,52 @@ +import { PATH } from 'consts/urls'; +import { SiweAuthGate } from 'modules/siwe'; +import { SurveysAuthProvider } from 'modules/surveys-sdk'; +import { FC, useMemo } from 'react'; +import { NoSSRWrapper } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { SurveysContactsPage } from './surveys-contacts-page'; +import { SurveysDelegatesPage } from './surveys-delegates-page'; +import { SurveysDelegatorPage } from './surveys-delegator-page'; +import { SurveysExperiencePage } from './surveys-experience-page'; +import { SurveysHomePage } from './surveys-home-page'; +import { SurveysHowDidYouLearnCsmPage } from './surveys-how-did-you-learn-page'; +import { SurveyProvider } from './surveys-provider'; +import { SurveysSetupPage } from './surveys-setup-page'; +import { SurveysSignInPage } from './surveys-signin-page'; + +export const SurveysPage: FC<{ slug?: string[] }> = ({ slug = [] }) => { + const page = useMemo(() => { + const [page, id1, id2] = slug; + const path = `/surveys/${page}`; + + switch (path) { + case PATH.SURVEYS_CONTACTS: + return ; + case PATH.SURVEYS_DELEGATES: + return ; + case PATH.SURVEYS_EXPERIENCE: + return ; + case PATH.SURVEYS_HOW_DID_YOU_LEARN_CSM: + return ; + case PATH.SURVEYS_SETUP: + return ; + case PATH.SURVEYS_DELEGATOR: + return ; + + default: + return ; + } + }, [slug]); + + return ( + + + + }> + {page} + + + + + ); +}; diff --git a/features/surveys/surveys-provider/index.ts b/features/surveys/surveys-provider/index.ts new file mode 100644 index 000000000..a1915f17b --- /dev/null +++ b/features/surveys/surveys-provider/index.ts @@ -0,0 +1,7 @@ +export { + SurveysProvider as SurveyProvider, + useSurveyContext, +} from './survey-provider'; +export type { SurveyMode, SurveyContextValue } from './survey-provider'; +export { SurveyOperatorGate } from './survey-operator-gate'; +export { SurveyDelegatorGate } from './survey-delegator-gate'; diff --git a/features/surveys/surveys-provider/survey-delegator-gate.tsx b/features/surveys/surveys-provider/survey-delegator-gate.tsx new file mode 100644 index 000000000..b49106f7c --- /dev/null +++ b/features/surveys/surveys-provider/survey-delegator-gate.tsx @@ -0,0 +1,26 @@ +import { FC, PropsWithChildren } from 'react'; +import { PATH } from 'consts/urls'; +import { Navigate } from 'shared/navigate'; +import { WhenLoaded } from 'shared/components'; +import { useSurveyContext } from './survey-provider'; + +type Props = { + operatorId: string; +}; + +export const SurveyDelegatorGate: FC> = ({ + operatorId, + children, +}) => { + const { isLoading, delegatedOperators } = useSurveyContext(); + + return ( + + {delegatedOperators.includes(operatorId) ? ( + children + ) : ( + + )} + + ); +}; diff --git a/features/surveys/surveys-provider/survey-operator-gate.tsx b/features/surveys/surveys-provider/survey-operator-gate.tsx new file mode 100644 index 000000000..1789cbafd --- /dev/null +++ b/features/surveys/surveys-provider/survey-operator-gate.tsx @@ -0,0 +1,15 @@ +import { FC, PropsWithChildren } from 'react'; +import { PATH } from 'consts/urls'; +import { Navigate } from 'shared/navigate'; +import { WhenLoaded } from 'shared/components'; +import { useSurveyContext } from './survey-provider'; + +export const SurveyOperatorGate: FC = ({ children }) => { + const { isLoading, isOperator } = useSurveyContext(); + + return ( + + {isOperator ? children : } + + ); +}; diff --git a/features/surveys/surveys-provider/survey-provider.tsx b/features/surveys/surveys-provider/survey-provider.tsx new file mode 100644 index 000000000..d9723f074 --- /dev/null +++ b/features/surveys/surveys-provider/survey-provider.tsx @@ -0,0 +1,61 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useNodeOperator } from 'modules/web3'; +import { + createContext, + FC, + PropsWithChildren, + useContext, + useMemo, +} from 'react'; +import invariant from 'tiny-invariant'; +import { useDelegatedOperators } from './use-delegated-operators'; + +export type SurveyMode = + | { type: 'loading' } + | { type: 'operator'; operatorId: NodeOperatorId } + | { type: 'delegator'; delegatedOperators: string[] } + | { type: 'empty' }; + +export type SurveyContextValue = { + mode: SurveyMode; + isLoading: boolean; + isOperator: boolean; + delegatedOperators: string[]; +}; + +const SurveyContext = createContext(null); + +export const useSurveyContext = (): SurveyContextValue => { + const value = useContext(SurveyContext); + invariant(value, 'useSurveyContext must be used within SurveyProvider'); + return value; +}; + +export const SurveysProvider: FC = ({ children }) => { + const { nodeOperator, isPending: operatorPending } = useNodeOperator(); + const { data: delegatedOperators, isLoading: delegatorLoading } = + useDelegatedOperators(nodeOperator?.nodeOperatorId); + + const isLoading = operatorPending || delegatorLoading; + const isOperator = !!nodeOperator; + + const mode = useMemo((): SurveyMode => { + if (isLoading) return { type: 'loading' }; + if (nodeOperator) + return { type: 'operator', operatorId: nodeOperator.nodeOperatorId }; + if (delegatedOperators?.length) + return { type: 'delegator', delegatedOperators }; + return { type: 'empty' }; + }, [isLoading, nodeOperator, delegatedOperators]); + + const value: SurveyContextValue = { + mode, + isLoading, + isOperator, + delegatedOperators: delegatedOperators ?? [], + }; + + return ( + {children} + ); +}; diff --git a/features/surveys/surveys-provider/use-delegated-operators.ts b/features/surveys/surveys-provider/use-delegated-operators.ts new file mode 100644 index 000000000..fed9ced2f --- /dev/null +++ b/features/surveys/surveys-provider/use-delegated-operators.ts @@ -0,0 +1,22 @@ +import { + endpoints, + useOperatorKey, + useSurveysQuery, +} from 'modules/surveys-sdk'; +import { useCallback } from 'react'; +import { DelegatedOperatorsResponse } from '../types'; + +export const useDelegatedOperators = (nodeOperatorId?: bigint) => { + const excludeId = useOperatorKey(nodeOperatorId); + + const select = useCallback( + (data: DelegatedOperatorsResponse) => + data.nodeOperatorIds.filter((id) => id !== excludeId), + [excludeId], + ); + + return useSurveysQuery( + endpoints.myDelegates, + { select }, + ); +}; diff --git a/features/surveys/surveys-setup-page.tsx b/features/surveys/surveys-setup-page.tsx index 5cbe9accd..945a5e87f 100644 --- a/features/surveys/surveys-setup-page.tsx +++ b/features/surveys/surveys-setup-page.tsx @@ -1,15 +1,10 @@ import { FC } from 'react'; -import { NoSSRWrapper } from 'shared/components'; -import { Layout } from 'shared/layout'; -import { BackButton } from './shared'; import { SurveySetup } from './survey-setup'; +import { SurveyOperatorGate } from './surveys-provider'; export const SurveysSetupPage: FC<{ id?: string }> = ({ id }) => ( - - - - - - + + + ); diff --git a/features/surveys/surveys-signin-page.tsx b/features/surveys/surveys-signin-page.tsx index ea991b160..e7921a1b2 100644 --- a/features/surveys/surveys-signin-page.tsx +++ b/features/surveys/surveys-signin-page.tsx @@ -1,13 +1,10 @@ import { FC } from 'react'; -import { NoSSRWrapper } from 'shared/components'; -import { Layout } from 'shared/layout'; -import { SiweSignIn } from './siwe-sign-in'; +import { useDappStatus } from 'modules/web3'; +import { SiweConnect, SiweSignIn } from './siwe-sign-in'; -export const SurveysSignInPage: FC = () => ( - - - - - -); +export const SurveysSignInPage: FC = () => { + const { isAccountActive } = useDappStatus(); + + return <>{isAccountActive ? : }; +}; diff --git a/features/surveys/types.ts b/features/surveys/types.ts index abc1360d5..b660f664e 100644 --- a/features/surveys/types.ts +++ b/features/surveys/types.ts @@ -1,5 +1,3 @@ -import { BigNumber } from 'ethers'; - export type Contact = { name?: string; discord?: string; @@ -30,6 +28,7 @@ export type SetupsKeys = { }; export type Setup = { + updatedAt: string; index: number; keysCount: number; dvt: string; @@ -37,17 +36,17 @@ export type Setup = { elClient: string; clClient: string; clinetsServerType: string; - clientsCountry: string; + clientsCountry?: string; validatorClient: string; validatorServerType: string; - validatorCountry: string; + validatorCountry?: string; validatorSameAsCl?: boolean; remoteSigner: string; - mevMinBid?: BigNumber; + mevMinBid?: bigint; }; export type SetupRaw = Omit & { - mevMinBid?: string; + mevMinBid?: string | null; }; export type Summary = { @@ -55,4 +54,19 @@ export type Summary = { setups: SetupRaw[]; experience: Experience | null; howDidYouLearnCsm: HowDidYouLearnCsm | null; + delegates: Delegate[]; +}; + +export type Delegate = { + address: string; +}; + +export type DelegatesResponse = { + delegates: Delegate[]; +}; + +export const MAX_DELEGATES = 5; + +export type DelegatedOperatorsResponse = { + nodeOperatorIds: string[]; // e.g., ['csm-1', 'csm-42'] }; diff --git a/features/type-parameters/ics-parameters-page.tsx b/features/type-parameters/ics-parameters-page.tsx new file mode 100644 index 000000000..11f6e92d1 --- /dev/null +++ b/features/type-parameters/ics-parameters-page.tsx @@ -0,0 +1,27 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { FAQ_OPERATOR_TYPE } from 'faq'; +import { IcsApplyButton } from 'features/ics/apply-button'; +import { IcsProviders } from 'features/ics/shared'; +import { FC } from 'react'; +import { Faq, TypeBackButton } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { IcsPageSwitcher } from 'shared/navigate'; +import { SingleTypeParameters } from './single-type-parameters'; + +export const IcsParametersPage: FC = () => ( + } + > + + + } + /> + + + +); diff --git a/features/type-parameters/idvtc-parameters-page.tsx b/features/type-parameters/idvtc-parameters-page.tsx new file mode 100644 index 000000000..5d1ed0c15 --- /dev/null +++ b/features/type-parameters/idvtc-parameters-page.tsx @@ -0,0 +1,27 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { FAQ_OPERATOR_TYPE } from 'faq'; +import { DvtApplyButton } from 'features/dvt/apply-button'; +import { DvtProviders } from 'features/dvt/shared'; +import { FC } from 'react'; +import { Faq, TypeBackButton } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { DvtPageSwitcher } from 'shared/navigate'; +import { SingleTypeParameters } from './single-type-parameters'; + +export const IdvtcParametersPage: FC = () => ( + } + > + + + } + /> + + + +); diff --git a/features/type-parameters/index.ts b/features/type-parameters/index.ts new file mode 100644 index 000000000..a5714a803 --- /dev/null +++ b/features/type-parameters/index.ts @@ -0,0 +1,5 @@ +export * from './ics-parameters-page'; +export * from './idvtc-parameters-page'; +export * from './single-type-parameters'; +export * from './type-parameters'; +export * from './type-parameters-page'; diff --git a/features/type-parameters/single-type-parameters.tsx b/features/type-parameters/single-type-parameters.tsx new file mode 100644 index 000000000..fe2ee3e52 --- /dev/null +++ b/features/type-parameters/single-type-parameters.tsx @@ -0,0 +1,78 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { OPERATOR_TYPE_METADATA } from 'consts'; +import { + useCurveParameters, + useNodeOperatorId, + useOperatorCurveId, +} from 'modules/web3'; +import { FC, ReactNode } from 'react'; +import { Block, CompareParametersList, Stack } from 'shared/components'; +import { DefColumnBackground, IcsColumnBackground } from 'shared/components'; +import { IdvtcColumnBackground } from 'shared/components/parameters-list/styles'; +import { useCurveMetadata, useOperatorTypeCurveId } from 'shared/hooks'; + +type SingleTypeParametersProps = { + type: OPERATOR_TYPE.CSM_ICS | OPERATOR_TYPE.CSM_IDVTC; + action?: ReactNode; +}; + +export const SingleTypeParameters: FC = ({ + type, + action, +}) => { + const nodeOperatorId = useNodeOperatorId(); + const { data: operatorCurveId } = useOperatorCurveId(nodeOperatorId); + + const typeCurveId = useOperatorTypeCurveId(type); + const defCurveId = useOperatorTypeCurveId(OPERATOR_TYPE.CSM_DEF); + + const currentCurveId = + nodeOperatorId !== undefined && + operatorCurveId !== undefined && + operatorCurveId !== typeCurveId + ? operatorCurveId + : defCurveId; + + const { data: currentParams } = useCurveParameters(currentCurveId); + const { data: typeParams } = useCurveParameters(typeCurveId); + + const currentTitle = useCurveMetadata(currentCurveId)?.title ?? ''; + + const TypeColumnBackground = + type === OPERATOR_TYPE.CSM_ICS + ? IcsColumnBackground + : IdvtcColumnBackground; + + return ( + + + + Explore the differences in node operator parameters across different + node operator types: + + + + + + + + + + {action} + + + + ); +}; diff --git a/features/type-parameters/type-parameters-page.tsx b/features/type-parameters/type-parameters-page.tsx new file mode 100644 index 000000000..62801c3d1 --- /dev/null +++ b/features/type-parameters/type-parameters-page.tsx @@ -0,0 +1,24 @@ +import { FAQ_OPERATOR_TYPE } from 'faq'; +import { IcsProviders } from 'features/ics/shared'; +import { FC } from 'react'; +import { ExtraWidth, Faq, TypeBackButton } from 'shared/components'; +import { Layout } from 'shared/layout'; +import { TypePageSwitcher } from 'shared/navigate'; +import { TypeParameters } from './type-parameters'; + +export const TypeParametersPage: FC = () => ( + } + > + + + + + + + + +); diff --git a/features/type-parameters/type-parameters.tsx b/features/type-parameters/type-parameters.tsx new file mode 100644 index 000000000..29776c4dd --- /dev/null +++ b/features/type-parameters/type-parameters.tsx @@ -0,0 +1,62 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { OPERATOR_TYPE_METADATA } from 'consts'; +import { IcsApplyButton } from 'features/ics/apply-button'; +import { useCurveParameters } from 'modules/web3'; +import { FC } from 'react'; +import { Block, CompareParametersList, Stack } from 'shared/components'; +import { DefColumnBackground, IcsColumnBackground } from 'shared/components'; +import { IdvtcColumnBackground } from 'shared/components/parameters-list/styles'; +import { useOperatorTypeCurveId, useShowFlags } from 'shared/hooks'; + +export const TypeParameters: FC = () => { + const { ICS_APPLY_ENABLED, CAN_CLAIM_ICS } = useShowFlags(); + + const { data: defParams } = useCurveParameters( + useOperatorTypeCurveId(OPERATOR_TYPE.CSM_DEF), + ); + const { data: icsParams } = useCurveParameters( + useOperatorTypeCurveId(OPERATOR_TYPE.CSM_ICS), + ); + const { data: idvtcParams } = useCurveParameters( + useOperatorTypeCurveId(OPERATOR_TYPE.CSM_IDVTC), + ); + + return ( + + + + Explore the differences in node operator parameters across different + node operator types: + + + + + + + + + + + {(ICS_APPLY_ENABLED || CAN_CLAIM_ICS) && } + + + + ); +}; diff --git a/features/unlock-bond/penalty-history/index.ts b/features/unlock-bond/penalty-history/index.ts new file mode 100644 index 000000000..683aa7d86 --- /dev/null +++ b/features/unlock-bond/penalty-history/index.ts @@ -0,0 +1 @@ +export { PenaltyHistory } from './penalty-history'; diff --git a/features/unlock-bond/penalty-history/penalty-history-table.tsx b/features/unlock-bond/penalty-history/penalty-history-table.tsx new file mode 100644 index 000000000..adf967412 --- /dev/null +++ b/features/unlock-bond/penalty-history/penalty-history-table.tsx @@ -0,0 +1,83 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { External, Text } from '@lidofinance/lido-ui'; +import { SortButton, useTable } from 'providers/table-provider'; +import { FC } from 'react'; +import { Stack, TxLinkEtherscan } from 'shared/components'; +import { FormatToken } from 'shared/formatters'; +import { formatDate } from 'utils'; +import { TableStyle } from './styles'; +import { EnrichedPenalty } from './types'; + +export const PenaltyHistoryTable: FC = () => { + const { data } = useTable(); + + return ( + + + + + Date + + + Type + + + Additional fine + + + Penalty sum + + Details + + + + {data.map((record) => ( + + + + {formatDate(record.timestamp, 'dd.MM.yyyy')} + } + /> + + {/* {record.details && {record.details}} */} + + {record.typeLabel} + + {(record.additionalFine !== undefined && ( + + + + )) || <>—} + + + + + + + + {record.details && ( + + {record.details} + + )} + + + ))} + + + ); +}; diff --git a/features/unlock-bond/penalty-history/penalty-history.tsx b/features/unlock-bond/penalty-history/penalty-history.tsx new file mode 100644 index 000000000..0d4840e9e --- /dev/null +++ b/features/unlock-bond/penalty-history/penalty-history.tsx @@ -0,0 +1,63 @@ +import type { PenaltyRecord } from '@lidofinance/lido-csm-sdk'; +import { Divider, Text } from '@lidofinance/lido-ui'; +import { useNodeOperatorId, useOperatorPenalties } from 'modules/web3'; +import { TablePagination, TableProvider } from 'providers/table-provider'; +import { FC } from 'react'; +import { Stack, WhenLoaded } from 'shared/components'; +import { PenaltyHistoryTable } from './penalty-history-table'; +import { sortFunctions } from './sort'; +import { AccordionStyle, Wrapper } from './styles'; +import { EnrichedPenalty } from './types'; + +const getPenaltyTypeLabel = (record: PenaltyRecord): string => { + if (record.type === 'compensated') return 'Compensation'; + if (record.type === 'cancelled') return 'Cancelled'; + if (record.type === 'settled') return 'Settled'; + if (record.type === 'expired') return 'Expired'; + if (!record.penaltyType) return 'EL Stealing Penalty'; + // return record.penaltyType || 'Penalty'; + return 'Penalty'; +}; + +const enrichPenalty = (record: PenaltyRecord): EnrichedPenalty => ({ + ...record, + typeLabel: getPenaltyTypeLabel(record), +}); + +export const PenaltyHistory: FC = () => { + const nodeOperatorId = useNodeOperatorId(); + + const { data, isPending } = useOperatorPenalties(nodeOperatorId, (data) => + data.map(enrichPenalty), + ); + + return ( + + Penalty History + + } + defaultExpanded={false} + > + + + + + + + + + + + + + ); +}; diff --git a/features/unlock-bond/penalty-history/sort.ts b/features/unlock-bond/penalty-history/sort.ts new file mode 100644 index 000000000..81f117b87 --- /dev/null +++ b/features/unlock-bond/penalty-history/sort.ts @@ -0,0 +1,29 @@ +import { SortCriteria, SortFunctions } from 'providers/table-provider'; +import { EnrichedPenalty } from './types'; + +const sortByDate: SortCriteria = (item) => [item.timestamp]; + +const typePriority: Record = { + settled: 0, + compensated: 1, + cancelled: 2, + expired: 3, + reported: 4, +}; + +const sortByType: SortCriteria = (item) => [ + typePriority[item.type], +]; + +const sortByAdditionalFine: SortCriteria = (item) => [ + item.additionalFine, +]; + +const sortByAmount: SortCriteria = (item) => [item.amount]; + +export const sortFunctions: SortFunctions = { + timestamp: sortByDate, + typeLabel: sortByType, + additionalFine: sortByAdditionalFine, + amount: sortByAmount, +}; diff --git a/features/unlock-bond/penalty-history/styles.ts b/features/unlock-bond/penalty-history/styles.ts new file mode 100644 index 000000000..c23ce3e67 --- /dev/null +++ b/features/unlock-bond/penalty-history/styles.ts @@ -0,0 +1,53 @@ +import { Accordion } from '@lidofinance/lido-ui'; +import { Table } from 'shared/components'; +import styled from 'styled-components'; + +export const AccordionStyle = styled(Accordion)` + & > div + div > div { + padding-inline: 0; + padding-block-end: ${({ theme }) => theme.spaceMap.md}px; + } +`; + +export const Wrapper = styled.div` + margin-inline: ${({ theme }) => theme.spaceMap.xxl}px; +`; + +export const TableStyle = styled(Table)` + grid-template-columns: 2fr 4fr 3fr 3fr; + + tr { + gap: 8px 20px; + + ${({ theme }) => theme.mediaQueries.md} { + grid-template-columns: 1fr; + padding: 20px 32px; + } + } + + th:nth-child(3), + th:nth-child(4), + td:nth-child(3), + td:nth-child(4) { + text-align: right; + justify-self: end; + } + + thead { + ${({ theme }) => theme.mediaQueries.md} { + display: none; + } + } + + th:nth-child(5) { + display: none; + } + + td:nth-child(5) { + grid-column: 1 / -1; + + &:empty { + display: none; + } + } +`; diff --git a/features/unlock-bond/penalty-history/types.ts b/features/unlock-bond/penalty-history/types.ts new file mode 100644 index 000000000..0e344fa11 --- /dev/null +++ b/features/unlock-bond/penalty-history/types.ts @@ -0,0 +1,12 @@ +import type { PenaltyRecord } from '@lidofinance/lido-csm-sdk'; +import type { Hex } from 'viem'; + +export type EnrichedPenalty = { + transactionHash: Hex; + type: PenaltyRecord['type']; + typeLabel: string; + timestamp: number; + additionalFine?: bigint; + amount?: bigint; + details?: string; +}; diff --git a/features/unlock-bond/unlock-bond-form/context/index.ts b/features/unlock-bond/unlock-bond-form/context/index.ts index 2aa8778c5..233eda767 100644 --- a/features/unlock-bond/unlock-bond-form/context/index.ts +++ b/features/unlock-bond/unlock-bond-form/context/index.ts @@ -1,2 +1,4 @@ +export * from './unlock-bond-data-provider'; export * from './unlock-bond-form-provider'; export * from './types'; +export * from './use-unlock-bond-flow'; diff --git a/features/unlock-bond/unlock-bond-form/context/types.ts b/features/unlock-bond/unlock-bond-form/context/types.ts index 1fb47e033..f0657ac4b 100644 --- a/features/unlock-bond/unlock-bond-form/context/types.ts +++ b/features/unlock-bond/unlock-bond-form/context/types.ts @@ -1,13 +1,10 @@ -import { BigNumber } from 'ethers'; -import { LoadingRecord, NodeOperatorId } from 'types'; +import { BondBalance, NodeOperatorId } from '@lidofinance/lido-csm-sdk'; -export type UnlockBondFormInputType = { - amount?: BigNumber; -}; +export type UnlockBondFormInputType = Record; export type UnlockBondFormNetworkData = { - nodeOperatorId?: NodeOperatorId; - lockedBond?: BigNumber; - etherBalance?: BigNumber; - loading: LoadingRecord<'lockedBond' | 'etherBalance'>; + nodeOperatorId: NodeOperatorId; + bond: BondBalance; + isExpired: boolean; + compensationAmount: bigint; }; diff --git a/features/unlock-bond/unlock-bond-form/context/unlock-bond-data-provider.tsx b/features/unlock-bond/unlock-bond-form/context/unlock-bond-data-provider.tsx new file mode 100644 index 000000000..a537e1ae5 --- /dev/null +++ b/features/unlock-bond/unlock-bond-form/context/unlock-bond-data-provider.tsx @@ -0,0 +1,68 @@ +import { + KEY_OPERATOR_BALANCE, + KEY_IS_LOCK_EXPIRED, + useIsLockExpired, + useNodeOperatorId, + useOperatorBalance, + KEY_OPERATOR_PENALTIES, +} from 'modules/web3'; +import { FC, PropsWithChildren, useCallback } from 'react'; +import { + FormDataContext, + NetworkData, + useFormData, +} from 'shared/hook-form/form-controller'; +import { useInvalidate } from 'shared/hooks'; +import { type UnlockBondFormNetworkData } from './types'; +import { bigMin } from 'utils'; + +const useUnlockBondFormNetworkData: NetworkData< + UnlockBondFormNetworkData +> = () => { + const nodeOperatorId = useNodeOperatorId(); + + const balanceQuery = useOperatorBalance(nodeOperatorId); + + const isExpiredQuery = useIsLockExpired(nodeOperatorId); + + const bond = balanceQuery.data; + const isExpired = !!isExpiredQuery.data; + + const compensationAmount = + !isExpired && !bond?.isInsufficient + ? bigMin(bond?.delta || 0n, bond?.locked || 0n) + : 0n; + + const invalidate = useInvalidate(); + + const revalidate = useCallback(() => { + invalidate([ + KEY_OPERATOR_BALANCE, + KEY_IS_LOCK_EXPIRED, + KEY_OPERATOR_PENALTIES, + ]); + }, [invalidate]); + + return { + data: { + nodeOperatorId, + bond, + isExpired, + compensationAmount, + } as UnlockBondFormNetworkData, + isPending: balanceQuery.isPending || isExpiredQuery.isPending, + revalidate, + }; +}; + +export const useUnlockBondFormData = useFormData; + +export const UnlockBondDataProvider: FC = ({ children }) => { + const networkData = useUnlockBondFormNetworkData(); + + return ( + + {children} + + ); +}; diff --git a/features/unlock-bond/unlock-bond-form/context/unlock-bond-form-provider.tsx b/features/unlock-bond/unlock-bond-form/context/unlock-bond-form-provider.tsx index 1f37e6331..729346dd7 100644 --- a/features/unlock-bond/unlock-bond-form/context/unlock-bond-form-provider.tsx +++ b/features/unlock-bond/unlock-bond-form/context/unlock-bond-form-provider.tsx @@ -1,60 +1,24 @@ -import { FC, PropsWithChildren, useMemo } from 'react'; +import { FC, PropsWithChildren } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { - FormControllerContext, - FormControllerContextValueType, - FormDataContext, - useFormControllerRetry, - useFormData, + FormControllerProvider, + useFlowSubmit, } from 'shared/hook-form/form-controller'; -import { - UnlockBondFormNetworkData, - type UnlockBondFormInputType, -} from './types'; -import { useUnlockBondFormNetworkData } from './use-unlock-bond-form-network-data'; -import { useUnlockBondSubmit } from './use-unlock-bond-submit'; -import { useUnlockBondValidation } from './use-unlock-bond-validation'; - -export const useUnlockBondFormData = useFormData; +import { type UnlockBondFormInputType } from './types'; +import { useUnlockBondFlowResolver } from './use-unlock-bond-flow'; export const UnlockBondFormProvider: FC = ({ children }) => { - const [networkData, revalidate] = useUnlockBondFormNetworkData(); - const validationResolver = useUnlockBondValidation(networkData); - - // TODO: validate (max amount) const formObject = useForm({ - defaultValues: { - amount: undefined, - }, - resolver: validationResolver, mode: 'onChange', }); - const { retryEvent, retryFire } = useFormControllerRetry(); - - const { unlockBond } = useUnlockBondSubmit({ - onConfirm: revalidate, - onRetry: retryFire, - }); - - const formControllerValue: FormControllerContextValueType< - UnlockBondFormInputType, - UnlockBondFormNetworkData - > = useMemo( - () => ({ - onSubmit: unlockBond, - retryEvent, - }), - [unlockBond, retryEvent], - ); + const submitter = useFlowSubmit(useUnlockBondFlowResolver()); return ( - - - {children} - - + + {children} + ); }; diff --git a/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-flow.ts b/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-flow.ts new file mode 100644 index 000000000..7ab4d9de3 --- /dev/null +++ b/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-flow.ts @@ -0,0 +1,84 @@ +import { type MethodAccess } from '@lidofinance/lido-csm-sdk'; +import { useSmSDK } from 'modules/web3'; +import { useCallback } from 'react'; +import { + type Executable, + type FlowResolver, +} from 'shared/hook-form/form-controller'; +import { useCanPerform } from 'shared/hooks'; +import { useTxModalStagesCompensate } from '../hooks/use-tx-modal-stages-compensate'; +import { useTxModalStagesUnlockExpired } from '../hooks/use-tx-modal-stages-unlock-expired'; +import { useUnlockBondFormData } from './unlock-bond-data-provider'; +import { UnlockBondFormInputType, UnlockBondFormNetworkData } from './types'; + +export type UnlockBondFlow = + | { action: 'nothing' } + | { action: 'no-access'; access: MethodAccess } + | { action: 'insufficient-bond' } + | ({ action: 'compensate' } & Executable) + | ({ action: 'unlock-expired' } & Executable); + +export const useUnlockBondFlowResolver = (): FlowResolver< + UnlockBondFormInputType, + UnlockBondFormNetworkData, + UnlockBondFlow +> => { + const { bond: bondSDK } = useSmSDK(); + const [canCompensate, compensateAccess] = useCanPerform( + bondSDK, + 'compensateLockedBond', + ); + const [canUnlockExpired, unlockExpiredAccess] = useCanPerform( + bondSDK, + 'unlockExpiredLock', + ); + const buildCompensateCallback = useTxModalStagesCompensate(); + const buildUnlockExpiredCallback = useTxModalStagesUnlockExpired(); + + return useCallback( + (input, data) => { + if (!data.bond?.locked) return { action: 'nothing' }; + if (data.isExpired && !canUnlockExpired) + return { action: 'no-access', access: unlockExpiredAccess }; + if (!data.isExpired && !canCompensate) + return { action: 'no-access', access: compensateAccess }; + if (!data.isExpired && !data.compensationAmount) + return { action: 'insufficient-bond' }; + + if (data.isExpired) + return { + action: 'unlock-expired' as const, + submit: () => + bondSDK.unlockExpiredLock({ + nodeOperatorId: data.nodeOperatorId, + callback: buildUnlockExpiredCallback(input, data), + }), + }; + + return { + action: 'compensate' as const, + submit: () => + bondSDK.compensateLockedBond({ + nodeOperatorId: data.nodeOperatorId, + callback: buildCompensateCallback(input, data), + }), + }; + }, + [ + bondSDK, + canCompensate, + compensateAccess, + canUnlockExpired, + unlockExpiredAccess, + buildCompensateCallback, + buildUnlockExpiredCallback, + ], + ); +}; + +export const useUnlockBondFlow = (): UnlockBondFlow => { + const resolve = useUnlockBondFlowResolver(); + const data = useUnlockBondFormData(true); + const input: UnlockBondFormInputType = {}; + return resolve(input, data); +}; diff --git a/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-form-network-data.tsx b/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-form-network-data.tsx deleted file mode 100644 index 156fb31df..000000000 --- a/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-form-network-data.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { useCallback, useMemo } from 'react'; -import { useNodeOperatorLockAmount } from 'shared/hooks'; -import { type UnlockBondFormNetworkData } from './types'; -import { useEthereumBalance } from '@lido-sdk/react'; -import { STRATEGY_LAZY } from 'consts/swr-strategies'; - -export const useUnlockBondFormNetworkData = (): [ - UnlockBondFormNetworkData, - () => Promise, -] => { - const nodeOperatorId = useNodeOperatorId(); - - const { - data: lockedBond, - update: updateLockedBond, - initialLoading: isLockedBondLoading, - } = useNodeOperatorLockAmount(nodeOperatorId); - - const { - data: etherBalance, - update: updateEtherBalance, - initialLoading: isEtherBalanceLoading, - } = useEthereumBalance(undefined, STRATEGY_LAZY); - - const revalidate = useCallback(async () => { - await Promise.allSettled([updateLockedBond(), updateEtherBalance()]); - }, [updateEtherBalance, updateLockedBond]); - - const loading = useMemo( - () => ({ - isLockedBondLoading, - isEtherBalanceLoading, - }), - [isEtherBalanceLoading, isLockedBondLoading], - ); - - return [ - { - nodeOperatorId, - lockedBond, - etherBalance, - loading, - }, - revalidate, - ]; -}; diff --git a/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-submit.ts b/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-submit.ts deleted file mode 100644 index 041906375..000000000 --- a/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-submit.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { BigNumber } from 'ethers'; -import { useCallback } from 'react'; -import invariant from 'tiny-invariant'; - -import { useCSAccountingRPC, useCSModuleWeb3, useSendTx } from 'shared/hooks'; -import { handleTxError } from 'shared/transaction-modal'; -import { NodeOperatorId } from 'types'; -import { runWithTransactionLogger } from 'utils'; -import { UnlockBondFormInputType, UnlockBondFormNetworkData } from '../context'; -import { useTxModalStagesUnlockBond } from '../hooks/use-tx-modal-stages-unlock-bond'; - -type UseUnlockBondOptions = { - onConfirm?: () => Promise | void; - onRetry?: () => void; -}; - -type UnlockBondMethodParams = { - nodeOperatorId: NodeOperatorId; - amount: BigNumber; -}; - -// encapsulates eth/steth/wsteth flows -const useUnlockBondTx = () => { - const CSModuleWeb3 = useCSModuleWeb3(); - - return useCallback( - async (params: UnlockBondMethodParams) => { - invariant(CSModuleWeb3, 'must have CSModuleWeb3'); - - return { - tx: await CSModuleWeb3.populateTransaction.compensateELRewardsStealingPenalty( - params.nodeOperatorId, - { value: params.amount }, - ), - txName: 'compensateELRewardsStealingPenalty', - }; - }, - [CSModuleWeb3], - ); -}; - -export const useUnlockBondSubmit = ({ - onConfirm, - onRetry, -}: UseUnlockBondOptions) => { - const { txModalStages } = useTxModalStagesUnlockBond(); - const CSAccounting = useCSAccountingRPC(); - - const getTx = useUnlockBondTx(); - const sendTx = useSendTx(); - - const unlockBond = useCallback( - async ( - { amount }: UnlockBondFormInputType, - { nodeOperatorId }: UnlockBondFormNetworkData, - ): Promise => { - invariant(amount, 'BondAmount is not defined'); - invariant(nodeOperatorId, 'NodeOperatorId is not defined'); - - try { - txModalStages.sign({ amount }); - - const tx = await getTx({ - nodeOperatorId, - amount, - }); - - const [txHash, waitTx] = await runWithTransactionLogger( - 'UnlockBond signing', - () => sendTx(tx), - ); - - txModalStages.pending({ amount }, txHash); - - await runWithTransactionLogger('UnlockBond block confirmation', waitTx); - - await onConfirm?.(); - - // TODO: move to onConfirm - const current = await CSAccounting.getActualLockedBond(nodeOperatorId); - - txModalStages.success({ lockedBond: current }, txHash); - - return true; - } catch (error) { - return handleTxError(error, txModalStages, onRetry); - } - }, - [getTx, txModalStages, onConfirm, CSAccounting, sendTx, onRetry], - ); - - return { - unlockBond, - }; -}; diff --git a/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-validation.ts b/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-validation.ts deleted file mode 100644 index 7c0a2c2d9..000000000 --- a/features/unlock-bond/unlock-bond-form/context/use-unlock-bond-validation.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { formatEther } from '@ethersproject/units'; -import { TOKENS } from 'consts/tokens'; -import { useCallback } from 'react'; -import type { Resolver } from 'react-hook-form'; -import { - handleResolverValidationError, - validateBignumberMax, - validateEtherAmount, -} from 'shared/hook-form/validation'; -import { useAwaitNetworkData } from 'shared/hooks'; -import invariant from 'tiny-invariant'; -import { getTokenDisplayName } from 'utils'; -import type { - UnlockBondFormInputType, - UnlockBondFormNetworkData, -} from './types'; -import { Zero } from '@ethersproject/constants'; - -export const useUnlockBondValidation = ( - networkData: UnlockBondFormNetworkData, -) => { - const dataPromise = useAwaitNetworkData(networkData); - - return useCallback>( - async (values) => { - try { - const { amount } = values; - - const { lockedBond, etherBalance } = await dataPromise; - - invariant(etherBalance); - invariant(lockedBond); - - validateEtherAmount('amount', amount, TOKENS.ETH); - - validateBignumberMax( - 'amount', - amount ?? Zero, - etherBalance, - `Entered ${getTokenDisplayName(TOKENS.ETH)} amount exceeds your balance of ${formatEther( - etherBalance, - )}`, - ); - - validateBignumberMax( - 'amount', - amount ?? Zero, - lockedBond, - `Entered ${getTokenDisplayName(TOKENS.ETH)} amount exceeds locked bond of ${formatEther( - lockedBond, - )}`, - ); - - return { - values, - errors: {}, - }; - } catch (error) { - return handleResolverValidationError(error, 'UnlockBondForm', 'amount'); - } - }, - [dataPromise], - ); -}; diff --git a/features/unlock-bond/unlock-bond-form/controls/amount-input.tsx b/features/unlock-bond/unlock-bond-form/controls/amount-input.tsx deleted file mode 100644 index 5e74af95d..000000000 --- a/features/unlock-bond/unlock-bond-form/controls/amount-input.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { TOKENS } from 'consts/tokens'; -import { FormTitle, Note } from 'shared/components'; -import { TokenAmountInputHookForm } from 'shared/hook-form/controls'; -import { useMaxValue } from '../hooks/use-max-value'; - -export const AmountInput: React.FC = () => { - const max = useMaxValue(); - - // TODO: disable - return ( - <> - Enter token amount - - Locked bond can be compensated only in ETH - - ); -}; diff --git a/features/unlock-bond/unlock-bond-form/controls/compensating-amount.tsx b/features/unlock-bond/unlock-bond-form/controls/compensating-amount.tsx new file mode 100644 index 000000000..ee5070047 --- /dev/null +++ b/features/unlock-bond/unlock-bond-form/controls/compensating-amount.tsx @@ -0,0 +1,27 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { DisabledInputAmount, Stack } from 'shared/components'; +import { useUnlockBondFormData } from '../context'; + +export const CompensatingAmount: FC = () => { + const { compensationAmount } = useUnlockBondFormData(true); + + if (!compensationAmount) return null; + + return ( + + + + Will be deducted from your bond balance + + + ); +}; diff --git a/features/unlock-bond/unlock-bond-form/controls/info.tsx b/features/unlock-bond/unlock-bond-form/controls/info.tsx index f8e6a9fe2..71ea375e9 100644 --- a/features/unlock-bond/unlock-bond-form/controls/info.tsx +++ b/features/unlock-bond/unlock-bond-form/controls/info.tsx @@ -1,55 +1,84 @@ -import { TOKENS } from 'consts/tokens'; +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { BOND_EXCESS, BOND_INSUFFICIENT } from 'consts/text'; import { FC } from 'react'; -import { Latice, MatomoLink, Stack, TitledAmount } from 'shared/components'; -import { useUnlockBondFormData } from '../context'; +import { + Latice, + Stack, + StatusChip, + TitledAmount, + WarningBlock, +} from 'shared/components'; +import { useUnlockBondFlow, useUnlockBondFormData } from '../context'; +import { LocalLink } from 'shared/navigate'; +import { PATH } from 'consts'; export const Info: FC = () => { - const { lockedBond, loading } = useUnlockBondFormData(); + const { bond, isExpired } = useUnlockBondFormData(); + const flow = useUnlockBondFlow(); + + const showDelta = + flow.action === 'compensate' || flow.action === 'insufficient-bond'; + return ( <> - {lockedBond?.gt(0) && ( -

          - - EL reward stealing - {' '} - penalties have been applied to your Node Operator because one of - your validators produced a block with the EL rewards sent to the - wrong address (an address different from from{' '} - - the Lido Execution Layer Rewards Vault - + chip={ + isExpired && + !!bond?.locked && ( + + Expired + ) -
          - Actions required: -

            -
          • - Compensate the amount of the penalty, otherwise the - corresponding part of your bond will be burned and your - beneficial bond curve will be reset to the default one.{' '} -
          • -
          • - Check if the feeRecipient address of your validators consensus - / validator client is set to{' '} - - the Lido Execution Layer Rewards Vault - {' '} - to avoid the further penalties. -
          • -
          -

          + } + amount={bond?.locked} + token={TOKENS.steth} + /> + {!!bond?.locked && + (isExpired ? ( +
          + The lock period has ended. You can unlock your bond now (no + compensation required). +
          + ) : ( +
          + Penalties have been applied to your Node Operator. If they + aren't covered, the corresponding amount of your bond may + be burned. See details in the table below. +
          + Actions required: +
            +
          • + Compensate the penalty amount to prevent the related portion + of your bond from being burned +
          • +
          • + Review the penalty details and fix the underlying issue to + avoid additional penalties +
          • +
          +
          + ))} + {showDelta && ( + )}
          + {flow.action === 'insufficient-bond' && ( + + Your bond is insufficient to compensate the locked amount. Please{' '} + top up the bond first. + + )} ); }; diff --git a/features/unlock-bond/unlock-bond-form/controls/submit-button.tsx b/features/unlock-bond/unlock-bond-form/controls/submit-button.tsx index eab102745..87a7a0453 100644 --- a/features/unlock-bond/unlock-bond-form/controls/submit-button.tsx +++ b/features/unlock-bond/unlock-bond-form/controls/submit-button.tsx @@ -1,10 +1,14 @@ import { SubmitButtonHookForm } from 'shared/hook-form/controls'; +import { useUnlockBondFlow } from '../context'; export const SubmitButton = () => { - // TODO: disable + const flow = useUnlockBondFlow(); + return ( - - Compensate locked bond + + {flow.action === 'unlock-expired' + ? 'Unlock bond' + : 'Compensate locked bond'} ); }; diff --git a/features/unlock-bond/unlock-bond-form/hooks/use-max-value.ts b/features/unlock-bond/unlock-bond-form/hooks/use-max-value.ts deleted file mode 100644 index 109192856..000000000 --- a/features/unlock-bond/unlock-bond-form/hooks/use-max-value.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Zero } from '@ethersproject/constants'; -import { useUnlockBondFormData } from '../context'; - -export const useMaxValue = () => { - const { lockedBond, etherBalance } = useUnlockBondFormData(); - return lockedBond && etherBalance - ? lockedBond?.lt(etherBalance) - ? lockedBond - : etherBalance - : Zero; -}; diff --git a/features/unlock-bond/unlock-bond-form/hooks/use-tx-modal-stages-compensate.tsx b/features/unlock-bond/unlock-bond-form/hooks/use-tx-modal-stages-compensate.tsx new file mode 100644 index 000000000..e3c2a16a7 --- /dev/null +++ b/features/unlock-bond/unlock-bond-form/hooks/use-tx-modal-stages-compensate.tsx @@ -0,0 +1,56 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { + TxAmount, + TxStageSignOperationAmount, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import { + UnlockBondFormInputType, + UnlockBondFormNetworkData, +} from '../context/types'; + +type TxResult = bigint | undefined; + +export const useTxModalStagesCompensate = () => + useTxStages( + (transitStage, _input, data) => ({ + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (result: TxResult, txHash) => + transitStage( + + Remaining locked bond{' '} + + + ) : undefined + } + />, + ), + }), + ); diff --git a/features/unlock-bond/unlock-bond-form/hooks/use-tx-modal-stages-unlock-bond.tsx b/features/unlock-bond/unlock-bond-form/hooks/use-tx-modal-stages-unlock-bond.tsx deleted file mode 100644 index de0127286..000000000 --- a/features/unlock-bond/unlock-bond-form/hooks/use-tx-modal-stages-unlock-bond.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import type { BigNumber } from 'ethers'; - -import { TOKENS } from 'consts/tokens'; -import { - TransactionModalTransitStage, - TxAmount, - TxStageSignOperationAmount, - TxStageSuccess, - getGeneralTransactionModalStages, - useTransactionModalStage, -} from 'shared/transaction-modal'; - -type Props = { - amount: BigNumber; -}; - -const getTxModalStagesUnlockBond = ( - transitStage: TransactionModalTransitStage, -) => ({ - ...getGeneralTransactionModalStages(transitStage), - - sign: ({ amount }: Props) => - transitStage( - , - ), - - pending: ({ amount }: Props, txHash?: string) => - transitStage( - , - ), - - success: ({ lockedBond }: { lockedBond: BigNumber }, txHash?: string) => - transitStage( - - Remaining locked bond{' '} - - - ) - } - />, - { - isClosableOnLedger: true, - }, - ), -}); - -export const useTxModalStagesUnlockBond = () => { - return useTransactionModalStage(getTxModalStagesUnlockBond); -}; diff --git a/features/unlock-bond/unlock-bond-form/hooks/use-tx-modal-stages-unlock-expired.tsx b/features/unlock-bond/unlock-bond-form/hooks/use-tx-modal-stages-unlock-expired.tsx new file mode 100644 index 000000000..3993a814c --- /dev/null +++ b/features/unlock-bond/unlock-bond-form/hooks/use-tx-modal-stages-unlock-expired.tsx @@ -0,0 +1,35 @@ +import { + TxStagePending, + TxStageSign, + TxStageSuccess, + useTxStages, +} from 'shared/transaction-modal'; +import { + UnlockBondFormInputType, + UnlockBondFormNetworkData, +} from '../context/types'; + +export const useTxModalStagesUnlockExpired = () => + useTxStages( + (transitStage) => ({ + sign: () => + transitStage( + , + ), + pending: (txHash) => + transitStage( + , + ), + success: (_result, txHash) => + transitStage( + , + ), + }), + ); diff --git a/features/unlock-bond/unlock-bond-form/unlock-bond-form-info.tsx b/features/unlock-bond/unlock-bond-form/unlock-bond-form-info.tsx index 09377fbf4..0dc19c58b 100644 --- a/features/unlock-bond/unlock-bond-form/unlock-bond-form-info.tsx +++ b/features/unlock-bond/unlock-bond-form/unlock-bond-form-info.tsx @@ -1,23 +1,19 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; import { DataTable, DataTableRow } from '@lidofinance/lido-ui'; -import { TOKENS } from 'consts/tokens'; -import { useWatch } from 'react-hook-form'; import { FormatToken } from 'shared/formatters'; -import { UnlockBondFormInputType, useUnlockBondFormData } from './context'; +import { useUnlockBondFormData } from './context'; export const UnlockBondFormInfo = () => { - const { - lockedBond, - loading: { isLockedBondLoading }, - } = useUnlockBondFormData(); + const { compensationAmount, bond } = useUnlockBondFormData(true); - const amount = useWatch({ - name: 'amount', - }); + if (!compensationAmount) return null; + + const remainingLocked = bond.locked - compensationAmount; return ( - - + + ); diff --git a/features/unlock-bond/unlock-bond-form/unlock-bond-form-loader.tsx b/features/unlock-bond/unlock-bond-form/unlock-bond-form-loader.tsx index 1dfa17674..379870ff9 100644 --- a/features/unlock-bond/unlock-bond-form/unlock-bond-form-loader.tsx +++ b/features/unlock-bond/unlock-bond-form/unlock-bond-form-loader.tsx @@ -1,18 +1,21 @@ import { FC, PropsWithChildren } from 'react'; -import { useFormState } from 'react-hook-form'; -import { WhenLoaded } from 'shared/components'; -import { UnlockBondFormInputType } from './context'; +import { FormLoader } from 'shared/hook-form/form-controller'; +import { useUnlockBondFlow } from './context'; import { Info } from './controls/info'; -import { useActiveNodeOperator } from 'providers/node-operator-provider'; -import { ROLES } from 'consts/roles'; -export const UnlockBondFormLoader: FC = ({ children }) => { - const nodeOperator = useActiveNodeOperator(); - const { isLoading } = useFormState(); +const UnlockBondFormGate: FC = ({ children }) => { + const flow = useUnlockBondFlow(); - const isView = !nodeOperator?.roles.includes(ROLES.MANAGER); + const isReadOnly = + flow.action === 'nothing' || + flow.action === 'no-access' || + flow.action === 'insufficient-bond'; - return ( - {isView ? : children} - ); + return isReadOnly ? : <>{children}; }; + +export const UnlockBondFormLoader: FC = ({ children }) => ( + + {children} + +); diff --git a/features/unlock-bond/unlock-bond-form/unlock-bond-form.tsx b/features/unlock-bond/unlock-bond-form/unlock-bond-form.tsx index df77c2cbe..c9978388f 100644 --- a/features/unlock-bond/unlock-bond-form/unlock-bond-form.tsx +++ b/features/unlock-bond/unlock-bond-form/unlock-bond-form.tsx @@ -1,28 +1,28 @@ import { FC, memo } from 'react'; - -import { UnlockBondFormProvider } from './context'; - -import { UnlockBondFormInfo } from './unlock-bond-form-info'; -import { AmountInput } from './controls/amount-input'; -import { SubmitButton } from './controls/submit-button'; import { FormBlock } from 'shared/components'; -import { FormControllerStyled } from 'shared/hook-form/form-controller'; +import { Form } from 'shared/hook-form/form-controller'; +import { UnlockBondDataProvider, UnlockBondFormProvider } from './context'; +import { CompensatingAmount } from './controls/compensating-amount'; import { Info } from './controls/info'; +import { SubmitButton } from './controls/submit-button'; +import { UnlockBondFormInfo } from './unlock-bond-form-info'; import { UnlockBondFormLoader } from './unlock-bond-form-loader'; export const UnlockBondForm: FC = memo(() => { return ( - - - - - - - - - - - - + + + + +
          + + + + + +
          +
          +
          +
          ); }); diff --git a/features/unlock-bond/unlock-bond-page.tsx b/features/unlock-bond/unlock-bond-page.tsx index 0105e2805..98ce94daf 100644 --- a/features/unlock-bond/unlock-bond-page.tsx +++ b/features/unlock-bond/unlock-bond-page.tsx @@ -3,15 +3,17 @@ import { FC } from 'react'; import { Layout } from 'shared/layout'; import { BondPageSwitcher } from 'shared/navigate'; import { UnlockBond } from './unlock-bond'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { Faq } from 'shared/components'; +import { FAQ_LOCKED } from 'faq'; export const UnlockBondPage: FC = () => ( + ); diff --git a/features/unlock-bond/unlock-bond.tsx b/features/unlock-bond/unlock-bond.tsx index 8eb8d20f7..f289b2457 100644 --- a/features/unlock-bond/unlock-bond.tsx +++ b/features/unlock-bond/unlock-bond.tsx @@ -1,8 +1,8 @@ import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; +import { useWeb3Key } from 'shared/hooks'; import { UnlockBondForm } from './unlock-bond-form'; -import { Faq } from 'shared/components'; +import { PenaltyHistory } from './penalty-history'; export const UnlockBond = () => { const key = useWeb3Key(); @@ -10,8 +10,8 @@ export const UnlockBond = () => { <> + - ); }; diff --git a/features/view-keys/deposit-queue/added-tooltip-content.tsx b/features/view-keys/deposit-queue/added-tooltip-content.tsx new file mode 100644 index 000000000..c30b22979 --- /dev/null +++ b/features/view-keys/deposit-queue/added-tooltip-content.tsx @@ -0,0 +1,31 @@ +import { Divider } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { getPriorityName } from './get-priority-name'; +import { TooltipContentStyle } from './style'; +import { BatchMetadata, GraphPart } from './types'; + +type AddedTooltipContentProps = { + metadata: BatchMetadata; +}; + +export const AddedTooltipContent: FC = ({ + metadata, +}) => { + return ( + + {metadata.map((item, index) => ( + <> + {index > 0 && } + + + {getPriorityName(`priority${item.priority}` as GraphPart)} + + Submitting keys: {item.keysCount.toString()} + Keys ahead: {item.position.toString()} + + + ))} + + ); +}; diff --git a/features/view-keys/deposit-queue/batch-tooltip-content.tsx b/features/view-keys/deposit-queue/batch-tooltip-content.tsx new file mode 100644 index 000000000..1d099e885 --- /dev/null +++ b/features/view-keys/deposit-queue/batch-tooltip-content.tsx @@ -0,0 +1,33 @@ +import { Divider } from '@lidofinance/lido-ui'; +import { FC, Fragment } from 'react'; +import { Stack } from 'shared/components'; +import { getPriorityName } from './get-priority-name'; +import { TooltipContentStyle } from './style'; +import { BatchMetadata, GraphPart } from './types'; + +type BatchTooltipContentProps = { + metadata: BatchMetadata; +}; + +export const BatchTooltipContent: FC = ({ + metadata, +}) => { + return ( + + {metadata.map((batch, index) => ( + + {index > 0 && } + + + {batch.combined + ? 'Multiple batches' + : getPriorityName(`priority${batch.priority}` as GraphPart)} + + Keys: {batch.keysCount.toString()} + Keys ahead: {batch.position.toString()} + + + ))} + + ); +}; diff --git a/features/view-keys/deposit-queue/deposit-queue-graph.tsx b/features/view-keys/deposit-queue/deposit-queue-graph.tsx index 1b018cbe5..cd81a9c17 100644 --- a/features/view-keys/deposit-queue/deposit-queue-graph.tsx +++ b/features/view-keys/deposit-queue/deposit-queue-graph.tsx @@ -1,70 +1,57 @@ import { InlineLoader } from '@lidofinance/lido-ui'; -import { FC, useState } from 'react'; +import { FC } from 'react'; import { Stack } from 'shared/components'; -import { HoverProvider } from './hover-provider'; +import { useDepositQueueGraph } from './hooks/use-deposit-queue-graph'; +import { + GraphInteractionProvider, + useGraphInteraction, +} from './hover-provider'; import { Legend } from './legend'; +import { LineWrapper } from './line-wrapper'; import { Part } from './part'; -import { FarStyle, LegendsStyle, LineStyle, WrapperStyle } from './style'; -import { useDepositQueueGraph } from './use-deposit-queue-graph'; +import { LegendsStyle, LineStyle } from './style'; -export const DepositQueueGraph: FC = () => { - const [fullView, setFullView] = useState(false); - const { graph, values, isLoading } = useDepositQueueGraph(fullView); +const Graph: FC = () => { + const { fullView } = useGraphInteraction(); + const { data, isLoading } = useDepositQueueGraph(fullView); - if (isLoading || !graph) { + if (isLoading || !data) { return ; } return ( - - - setFullView(false)}> - - - - - - - - - - - + + + + {data.parts.map((part, index) => ( + + ))} + {data.operator?.batches.map((batch, index) => ( + + ))} + + + + + {data.parts + .filter((part) => part.type !== 'added') + .map((part, index) => ( + + ))} + + + + + ); }; + +export const DepositQueueGraph: FC = () => ( + + + +); diff --git a/features/view-keys/deposit-queue/deposit-queue.tsx b/features/view-keys/deposit-queue/deposit-queue.tsx index 397d04843..ae2120fa7 100644 --- a/features/view-keys/deposit-queue/deposit-queue.tsx +++ b/features/view-keys/deposit-queue/deposit-queue.tsx @@ -1,4 +1,9 @@ import { Accordion, Text } from '@lidofinance/lido-ui'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts'; +import { + LIDO_OPERATOR_PORTAL_DEPOSITS_FLOW, + SUBSCRIBE_EVENTS_LINK, +} from 'consts/external-links'; import { FC } from 'react'; import { MatomoLink, Stack } from 'shared/components'; import { DepositQueueGraph } from './deposit-queue-graph'; @@ -18,21 +23,30 @@ export const DepositQueue: FC = () => ( The time to deposit a validator is unpredictable and depends on factors such as total stake inflows and outflows, gas considerations, module shares, CSM deposit queue size, and the Node Operator's - place in the queue. + place in the queue

          You can subscribe to{' '} - + the important CSM events {' '} - to stay notified about your validator being deposited to. + to stay notified about your validator being deposited to

          Read more information about{' '} - + the deposits flow - .

          diff --git a/features/view-keys/deposit-queue/get-priority-name.ts b/features/view-keys/deposit-queue/get-priority-name.ts new file mode 100644 index 000000000..512671563 --- /dev/null +++ b/features/view-keys/deposit-queue/get-priority-name.ts @@ -0,0 +1,44 @@ +import { GraphPart } from './types'; + +export const getPriorityName = (type: GraphPart) => { + switch (type) { + case 'active': + return 'Active keys'; + case 'batch': + return 'Your queued keys'; + case 'added': + return 'Keys you’re trying to submit'; + case 'limit': + return 'CSM stake limit'; + case 'queue': + return 'Queued keys'; + case 'queueOverLimit': + return 'Queued keys (over limit)'; + case 'priority0': + return 'Priority queue'; + case 'priority1': + return 'Priority 2 queue'; + case 'priority2': + return 'Priority 3 queue'; + case 'priority3': + return 'Priority 4 queue'; + case 'priority4': + return 'Priority 5 queue'; + case 'priority5': + return 'General queue'; + case 'priority0OverLimit': + return 'Priority queue (over limit)'; + case 'priority1OverLimit': + return 'Priority 2 queue (over limit)'; + case 'priority2OverLimit': + return 'Priority 3 queue (over limit)'; + case 'priority3OverLimit': + return 'Priority 4 queue (over limit)'; + case 'priority4OverLimit': + return 'Priority 5 queue (over limit)'; + case 'priority5OverLimit': + return 'General queue (over limit)'; + default: + return 'Unknown'; + } +}; diff --git a/features/view-keys/deposit-queue/hooks/calculate-and-select-by-operator.ts b/features/view-keys/deposit-queue/hooks/calculate-and-select-by-operator.ts new file mode 100644 index 000000000..f7860b797 --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/calculate-and-select-by-operator.ts @@ -0,0 +1,59 @@ +import { DepositQueueBatch } from '@lidofinance/lido-csm-sdk'; + +type OperatorBatch = { + keysCount: number; + offset: bigint; // Keys count before this batch (from other operators) +}; + +export type QueueAnalysis = { + queueIndex: number; + totalKeysInQueue: bigint; + operatorBatches: OperatorBatch[]; +}; + +export type DepositQueueAnalysis = { + totalKeysCount: bigint; + queueAnalysis: QueueAnalysis[]; +}; + +export const calculateAndSelectByOperator = ( + nodeOperatorId: bigint | undefined, +) => { + return (allBatches: DepositQueueBatch[][]): DepositQueueAnalysis => { + let totalKeysCount = 0n; + const queueAnalysis: QueueAnalysis[] = []; + + allBatches.forEach((batches, queueIndex) => { + let totalKeysInQueue = 0n; + let runningOffset = 0n; + const operatorBatches: OperatorBatch[] = []; + + batches.forEach((batch) => { + const isOperatorBatch = batch.nodeOperatorId === nodeOperatorId; + + if (isOperatorBatch) { + operatorBatches.push({ + keysCount: batch.keysCount, + offset: runningOffset, + }); + } + + runningOffset += BigInt(batch.keysCount); + totalKeysInQueue += BigInt(batch.keysCount); + }); + + totalKeysCount += totalKeysInQueue; + + queueAnalysis.push({ + queueIndex, + totalKeysInQueue, + operatorBatches, + }); + }); + + return { + totalKeysCount, + queueAnalysis, + }; + }; +}; diff --git a/features/view-keys/deposit-queue/hooks/calculate-priority-placement.ts b/features/view-keys/deposit-queue/hooks/calculate-priority-placement.ts new file mode 100644 index 000000000..99d03aa2d --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/calculate-priority-placement.ts @@ -0,0 +1,51 @@ +import type { OperatorInfo, SubmittingAllocation } from './enhanced-types'; + +const FALLBACK_LOWEST_PRIORITY = 5; + +type QueueConfig = { + priority: number; + maxDeposits: number; + lowestPriority: number; +}; + +export const calculatePriorityPlacement = ( + operatorInfo: OperatorInfo | undefined, + queueConfig: QueueConfig | undefined, + submittingCount: number | undefined, +): SubmittingAllocation | undefined => { + if (submittingCount === undefined) { + return undefined; + } + if (!operatorInfo || !queueConfig || !submittingCount) { + return { + keysCount: BigInt(submittingCount), + allocation: submittingCount + ? [[FALLBACK_LOWEST_PRIORITY, BigInt(submittingCount)]] + : [], + }; + } + + const { totalDepositedKeys = 0, enqueuedCount = 0 } = operatorInfo; + + const { priority, maxDeposits, lowestPriority } = queueConfig; + + // Calculate available priority slots + const depositedAndQueued = totalDepositedKeys + enqueuedCount; + const priorityDepositsLeft = Math.max(0, maxDeposits - depositedAndQueued); + + // Keys that will go to priority queue + const keysToPriority = Math.min(submittingCount, priorityDepositsLeft); + + // Remaining keys go to general queue (lowest priority) + const keysToLowestPriority = submittingCount - keysToPriority; + + const allocation = [ + [priority, BigInt(keysToPriority)], + [lowestPriority, BigInt(keysToLowestPriority)], + ].filter(([, count]) => count > 0) as [number, bigint][]; + + return { + keysCount: BigInt(submittingCount), + allocation, + }; +}; diff --git a/features/view-keys/deposit-queue/hooks/enhanced-types.ts b/features/view-keys/deposit-queue/hooks/enhanced-types.ts new file mode 100644 index 000000000..e49adf255 --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/enhanced-types.ts @@ -0,0 +1,73 @@ +import type { + QueueGraphData, + UseDepositQueueGraphResult, + BatchPart, + QueuePart, +} from '../types'; + +export type GraphBounds = { + startPosition: bigint; + endPosition: bigint; + range: bigint; + displayStart: number; + displayEnd: number; + displayRange: number; + minSegmentSize: number; + extraLow: boolean; + extraHigh: boolean; + farAway: boolean; +}; + +export type QueueSegment = { + keysUnderLimit: bigint; + keysOverLimit: bigint; + underLimitSize: number; + overLimitSize: number; + totalSize: number; + startPosition: bigint; +}; + +export type ViewConfig = { + fullView: boolean; + minSegmentSize: number; +}; + +export type ShareLimit = { + active: bigint; + queue: bigint; + capacity: bigint; + activeLeft: bigint; +}; + +export type OperatorInfo = { + depositableValidatorsCount?: number; + totalDepositedKeys?: number; + enqueuedCount?: number; +}; + +export type SubmittingAllocation = { + keysCount: bigint; + allocation: [number, bigint][]; +}; // queue priority, keys count + +export type ProcessedBatches = { + batches: BatchPart[]; + cumulativeKeys: bigint; +}; + +export type SegmentInfo = { + startPos: bigint; + underLimitKeys: bigint; + overLimitKeys: bigint; +}; + +export type GraphCalculationParams = { + active: bigint; + queue: bigint; + added: bigint; + capacity: bigint; + fullView: boolean; +}; + +// Re-export original types +export type { QueueGraphData, UseDepositQueueGraphResult, QueuePart }; diff --git a/features/view-keys/deposit-queue/hooks/graph-calculations.ts b/features/view-keys/deposit-queue/hooks/graph-calculations.ts new file mode 100644 index 000000000..a7499d331 --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/graph-calculations.ts @@ -0,0 +1,125 @@ +import { GRAPH_CONFIG } from './graph-config'; +import type { GraphBounds, GraphCalculationParams } from './enhanced-types'; + +export const calculateGraphBounds = ( + params: GraphCalculationParams, +): GraphBounds => { + const { active, queue, capacity, fullView } = params; + const { BACK_OFFSET, POTENTIAL_ADDED } = GRAPH_CONFIG.QUEUE; + const { LEFT_MARGIN, RIGHT_MARGIN, FULL_WIDTH } = GRAPH_CONFIG.VIEW.BOUNDS; + + const potential = + params.added < POTENTIAL_ADDED ? POTENTIAL_ADDED : params.added; + + // Calculate start position with back offset + const activeStart = active < BACK_OFFSET ? 0n : active; + const startPosition = fullView + ? 0n + : activeStart - BACK_OFFSET < 0n + ? activeStart + : activeStart - BACK_OFFSET; + + // Calculate end position + const endKeysPosition = active + queue + potential; + + // Check if capacity is far beyond queue end (before adjusting endPosition) + const extraHigh = + !fullView && capacity > endKeysPosition + endKeysPosition / 10n; + + // Include capacity in range when it's within reasonable distance + const endPosition = + endKeysPosition < capacity + ? extraHigh + ? endKeysPosition + : capacity + : endKeysPosition; + + const range = endPosition - startPosition; + + // Determine display boundaries based on view mode and capacity + const extraLow = !fullView && capacity < startPosition - range; + + const displayStart = fullView + ? 0 + : extraLow + ? LEFT_MARGIN + : startPosition > potential + ? LEFT_MARGIN + : 0; + + const displayEnd = fullView + ? FULL_WIDTH + : extraHigh + ? RIGHT_MARGIN + : FULL_WIDTH; + + const displayRange = displayEnd - displayStart; + const minSegmentSize = fullView + ? GRAPH_CONFIG.VIEW.MIN_SIZE_PERCENTAGE.FULL + : GRAPH_CONFIG.VIEW.MIN_SIZE_PERCENTAGE.NORMAL; + + const farAway = displayStart > 0; + + return { + startPosition, + endPosition, + range, + displayStart, + displayEnd, + displayRange, + minSegmentSize, + extraLow, + extraHigh, + farAway, + }; +}; + +export const normalizeToGraphCoordinate = ( + value: bigint, + bounds: GraphBounds, +): number => { + const { startPosition, displayStart, displayRange, range } = bounds; + + if (range === 0n) return displayStart; + + const relativePosition = Number( + ((value - startPosition) * BigInt(displayRange)) / range, + ); + return relativePosition + displayStart; +}; + +export const calculateSegmentSize = ( + value: bigint, + previousOffset: bigint, + bounds: GraphBounds, +): number => { + if (value === 0n) return 0; + + const { minSegmentSize } = bounds; + const previousPosition = + previousOffset === 0n + ? 0 + : Math.max( + minSegmentSize, + normalizeToGraphCoordinate(previousOffset, bounds), + ); + + const currentPosition = Math.max( + minSegmentSize, + normalizeToGraphCoordinate(value + previousOffset, bounds), + ); + + return Math.max(minSegmentSize, currentPosition - previousPosition); +}; + +export const calculateLimitOffset = ( + capacity: bigint, + bounds: GraphBounds, +): number => { + const { FULL_WIDTH } = GRAPH_CONFIG.VIEW.BOUNDS; + if (bounds.extraLow) return 8; + if (bounds.extraHigh) return GRAPH_CONFIG.VIEW.BOUNDS.FULL_WIDTH; + const offset = normalizeToGraphCoordinate(capacity, bounds); + if (offset < 0) return 0; + return offset > FULL_WIDTH ? FULL_WIDTH : offset; +}; diff --git a/features/view-keys/deposit-queue/hooks/graph-config.ts b/features/view-keys/deposit-queue/hooks/graph-config.ts new file mode 100644 index 000000000..a02d5b0e0 --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/graph-config.ts @@ -0,0 +1,17 @@ +export const GRAPH_CONFIG = { + QUEUE: { + POTENTIAL_ADDED: 25n, + BACK_OFFSET: 30n, + }, + VIEW: { + MIN_SIZE_PERCENTAGE: { + FULL: 0.5, + NORMAL: 1, + }, + BOUNDS: { + LEFT_MARGIN: 15, + RIGHT_MARGIN: 85, + FULL_WIDTH: 95, + }, + }, +} as const; diff --git a/features/view-keys/deposit-queue/hooks/operator-batch-collector.ts b/features/view-keys/deposit-queue/hooks/operator-batch-collector.ts new file mode 100644 index 000000000..7f9b8ab88 --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/operator-batch-collector.ts @@ -0,0 +1,213 @@ +import { BatchPart, OperatorQueue } from '../types'; +import { QueueAnalysis } from './calculate-and-select-by-operator'; +import type { GraphBounds, SubmittingAllocation } from './enhanced-types'; +import { normalizeToGraphCoordinate } from './graph-calculations'; + +const MAX_TOOLTIP_ITEMS = 2; + +type BatchInfo = { + keysCount: bigint; + absoluteOffset: bigint; // Position from the begining of active keys + queueOffset: bigint; // Position from the start of all queues + batchOffset: bigint; // Offset within its own queue + priority: number; +}; + +type CollectOperatorBatchesProps = { + queueDataList: QueueAnalysis[]; + activeKeys: bigint; + bounds: GraphBounds; + submittingAllocation?: SubmittingAllocation; +}; + +/** + * Collects all operator batches from multiple priority queues, + * converts them to graph coordinates, and combines adjacent batches. + */ +export const collectOperatorBatches = ({ + queueDataList, + activeKeys, + bounds, + submittingAllocation, +}: CollectOperatorBatchesProps): OperatorQueue => { + const allBatchInfos: BatchInfo[] = []; + let cumulativeKeys = 0n; + let submittingKeys = 0n; + + // Collect all batch information + queueDataList.forEach((queueData) => { + const keysCountInQueue = queueData.totalKeysInQueue; + + queueData.operatorBatches.forEach((batch) => { + const batchKeysCount = BigInt(batch.keysCount); + const batchOffset = batch.offset; + + allBatchInfos.push({ + keysCount: batchKeysCount, + absoluteOffset: + activeKeys + cumulativeKeys + submittingKeys + batchOffset, + queueOffset: cumulativeKeys + submittingKeys + batchOffset, + batchOffset, + priority: queueData.queueIndex, + }); + }); + + cumulativeKeys += keysCountInQueue; + + // Include submitting keys for this priority in cumulative position + const submittingKeysInPriority = + submittingAllocation?.allocation?.find( + ([priority]) => priority === queueData.queueIndex, + )?.[1] || 0n; + submittingKeys += submittingKeysInPriority; + }); + + // Convert to graph coordinates and combine adjacent batches + const graphBatches = convertToGraphBatches(allBatchInfos, bounds); + const combinedBatches = combineAdjacentBatches(graphBatches); + + // Sum operator batch keys only (not total queue keys) + const operatorKeysCount = allBatchInfos.reduce( + (sum, batch) => sum + batch.keysCount, + 0n, + ); + + return { + keysCount: operatorKeysCount, + batches: combinedBatches, + }; +}; + +/** + * Converts batch information to graph coordinates with normalized positions. + */ +const convertToGraphBatches = ( + batchInfos: BatchInfo[], + bounds: GraphBounds, +): BatchPart[] => { + const minSize = bounds.minSegmentSize; + + return batchInfos.map((batchInfo) => { + const startPos = normalizeToGraphCoordinate( + batchInfo.absoluteOffset, + bounds, + ); + const endPos = normalizeToGraphCoordinate( + batchInfo.absoluteOffset + batchInfo.keysCount, + bounds, + ); + + const size = Math.max(minSize, endPos - startPos); + + return { + offset: startPos, + width: size, + metadata: [ + { + keysCount: batchInfo.keysCount, + position: batchInfo.queueOffset, + priority: batchInfo.priority, + }, + ], + }; + }); +}; + +/** + * Merges two metadata arrays, combining consecutive entries with same priority. + */ +const mergeMetadataArrays = ( + first: BatchPart['metadata'] = [], + second: BatchPart['metadata'] = [], +): BatchPart['metadata'] => { + if (first.length > 0 && second.length > 0) { + const lastMeta = first[first.length - 1]; + const firstMeta = second[0]; + + const isConsecutive = + lastMeta.position + lastMeta.keysCount === firstMeta.position && + lastMeta.priority === firstMeta.priority; + + if (isConsecutive) { + const mergedMeta = { + position: lastMeta.position, + keysCount: lastMeta.keysCount + firstMeta.keysCount, + priority: lastMeta.priority, + }; + return [...first.slice(0, -1), mergedMeta, ...second.slice(1)]; + } + } + + return [...first, ...second]; +}; + +/** + * Ensures batch metadata doesn't exceed MAX_TOOLTIP_ITEMS. + * If exceeded, combines all metadata into a single entry with summed keys. + */ +const ensureMetadataWithinTooltipLimit = (batch: BatchPart): BatchPart => { + if (batch.metadata.length > MAX_TOOLTIP_ITEMS) { + const totalKeysCount = batch.metadata.reduce( + (sum, meta) => sum + meta.keysCount, + 0n, + ); + const firstMeta = batch.metadata[0]; + + return { + ...batch, + metadata: [ + { + keysCount: totalKeysCount, + position: firstMeta.position, + priority: firstMeta.priority, + combined: true, + }, + ], + }; + } + + return batch; +}; + +/** + * Combines adjacent or overlapping batches to reduce visual clutter. + * Uses a 0.5% tolerance for determining adjacency. + * Preserves individual batch metadata for tooltips. + */ +const combineAdjacentBatches = (batches: BatchPart[]): BatchPart[] => { + if (batches.length <= 1) return batches; + + // Sort by offset + const sortedBatches = [...batches].sort((a, b) => a.offset - b.offset); + const combined: BatchPart[] = []; + + let current = sortedBatches[0]; + + for (let i = 1; i < sortedBatches.length; i++) { + const next = sortedBatches[i]; + const currentEnd = current.offset + current.width; + + // Check if batches are adjacent or overlapping (with small tolerance for visual proximity) + const isAdjacent = next.offset - currentEnd <= 0.5; // 0.5px tolerance + + if (isAdjacent) { + // Combine batches by merging metadata arrays + const combinedEnd = Math.max(currentEnd, next.offset + next.width); + + current = { + offset: current.offset, + width: combinedEnd - current.offset, + metadata: mergeMetadataArrays(current.metadata, next.metadata), + }; + } else { + // Add current batch and start new one + combined.push(ensureMetadataWithinTooltipLimit(current)); + current = next; + } + } + + // Add the last batch + combined.push(ensureMetadataWithinTooltipLimit(current)); + + return combined; +}; diff --git a/features/view-keys/deposit-queue/hooks/use-deposit-queue-graph.ts b/features/view-keys/deposit-queue/hooks/use-deposit-queue-graph.ts new file mode 100644 index 000000000..75a48874f --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/use-deposit-queue-graph.ts @@ -0,0 +1,36 @@ +import { useMemo } from 'react'; +import type { UseDepositQueueGraphResult } from './enhanced-types'; +import { createMultiQueueVisualization } from './use-multi-queue'; +import { isMultiQueue, useQueueData } from './use-queue-data'; +import { createSingleQueueVisualization } from './use-single-queue'; + +export const useDepositQueueGraph = ( + fullView = false, +): UseDepositQueueGraphResult => { + const { shareLimit, queueAnalysis, submittingAllocation, isLoading } = + useQueueData(); + + return useMemo((): UseDepositQueueGraphResult => { + if (isLoading || !shareLimit) { + return { isLoading: true }; + } + + const data = isMultiQueue(queueAnalysis) + ? createMultiQueueVisualization( + queueAnalysis, + shareLimit, + submittingAllocation, + fullView, + ) + : createSingleQueueVisualization( + shareLimit, + submittingAllocation, + fullView, + ); + + return { + isLoading: false, + data, + }; + }, [isLoading, shareLimit, queueAnalysis, submittingAllocation, fullView]); +}; diff --git a/features/view-keys/deposit-queue/hooks/use-multi-queue.ts b/features/view-keys/deposit-queue/hooks/use-multi-queue.ts new file mode 100644 index 000000000..2e8d48434 --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/use-multi-queue.ts @@ -0,0 +1,145 @@ +import { GraphPart } from '../types'; +import type { DepositQueueAnalysis } from './calculate-and-select-by-operator'; +import type { + QueueGraphData, + QueuePart, + ShareLimit, + SubmittingAllocation, +} from './enhanced-types'; +import { + calculateGraphBounds, + calculateLimitOffset, + calculateSegmentSize, +} from './graph-calculations'; +import { collectOperatorBatches } from './operator-batch-collector'; + +const getPriorityType = (priority: number, overLimit: boolean): GraphPart => { + const base = `priority${priority}`; + const result = overLimit ? `${base}OverLimit` : base; + return result as GraphPart; +}; + +export const createMultiQueueVisualization = ( + queueAnalysis: DepositQueueAnalysis, + shareLimit: ShareLimit, + submittingAllocation: SubmittingAllocation | undefined, + fullView: boolean, +): QueueGraphData => { + const { active, queue, capacity, activeLeft } = shareLimit; + const added = submittingAllocation?.keysCount || 0n; + + // Calculate graph bounds and coordinates + const bounds = calculateGraphBounds({ + active, + queue, + capacity, + added, + fullView, + }); + + // Calculate segment sizes + const activeSize = calculateSegmentSize(active, 0n, bounds); + + const limitOffset = calculateLimitOffset(capacity, bounds); + + // Process multi-queue data + const { queueAnalysis: queues } = queueAnalysis; + + // Process priority queues and insert added keys at appropriate positions + const priorityQueues: QueuePart[] = []; + let cumulativeKeys = 0n; + let cumulativeAddedKeys = 0n; + + queues.forEach((queueData) => { + if (queueData.totalKeysInQueue > 0n) { + const keysInQueue = queueData.totalKeysInQueue; + + // Calculate queue segments + const queueUnderLimit = + activeLeft > 0n && cumulativeKeys < activeLeft + ? cumulativeKeys + keysInQueue <= activeLeft + ? keysInQueue + : activeLeft - cumulativeKeys + : 0n; + + const queueOverLimit = keysInQueue - queueUnderLimit; + const segmentStartPos = active + cumulativeKeys; + + const underLimitSize = calculateSegmentSize( + queueUnderLimit, + segmentStartPos, + bounds, + ); + + const overLimitSize = calculateSegmentSize( + queueOverLimit, + segmentStartPos + queueUnderLimit, + bounds, + ); + + priorityQueues.push( + { + type: getPriorityType(queueData.queueIndex, false), + keysCount: queueUnderLimit, + width: underLimitSize, + }, + { + type: getPriorityType(queueData.queueIndex, true), + keysCount: queueOverLimit, + width: overLimitSize, + }, + ); + + cumulativeKeys += keysInQueue; + } + + const [, submitting] = + submittingAllocation?.allocation?.find( + ([priority]) => priority === queueData.queueIndex, + ) || []; + + if (submitting) { + const addedPrioritySize = calculateSegmentSize( + submitting, + active + cumulativeKeys + cumulativeAddedKeys, + bounds, + ); + + priorityQueues.push({ + type: 'added', + keysCount: submitting, + width: addedPrioritySize, + metadata: [ + { + keysCount: submitting, + position: cumulativeKeys + cumulativeAddedKeys, + priority: queueData.queueIndex, + }, + ], + }); + + cumulativeAddedKeys += submitting; + } + }); + + const operatorData = collectOperatorBatches({ + queueDataList: queues, + activeKeys: active, + bounds, + submittingAllocation, + }); + + return { + parts: [ + { type: 'active', width: activeSize, keysCount: active }, + ...priorityQueues, + ], + limit: { + offset: limitOffset, + keysCount: capacity, + }, + operator: operatorData, + farAway: bounds.farAway, + submittingKeysCount: submittingAllocation?.keysCount, + }; +}; diff --git a/features/view-keys/deposit-queue/hooks/use-queue-data.ts b/features/view-keys/deposit-queue/hooks/use-queue-data.ts new file mode 100644 index 000000000..d63e97ed3 --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/use-queue-data.ts @@ -0,0 +1,70 @@ +import { + useCurveParameters, + useDepositQueueBatches, + useNodeOperatorId, + useOperatorInfo, + useShareLimit, +} from 'modules/web3'; +import { useFormContext } from 'react-hook-form'; +import { DepositDataInputType } from 'shared/hook-form/deposit-data'; +import { calculateAndSelectByOperator } from './calculate-and-select-by-operator'; +import type { + ShareLimit, + OperatorInfo, + SubmittingAllocation, +} from './enhanced-types'; +import type { DepositQueueAnalysis } from './calculate-and-select-by-operator'; +import { useCurrentCurveId } from 'shared/hooks'; +import { calculatePriorityPlacement } from './calculate-priority-placement'; + +export type QueueDataResult = { + nodeOperatorId: bigint | undefined; + operatorInfo: OperatorInfo | undefined; + shareLimit: ShareLimit | undefined; + queueAnalysis: DepositQueueAnalysis | undefined; + submittingAllocation: SubmittingAllocation | undefined; + isLoading: boolean; +}; + +export const useQueueData = (): QueueDataResult => { + const nodeOperatorId = useNodeOperatorId(); + const { data: operatorInfo } = useOperatorInfo(nodeOperatorId); + const { data: shareLimit } = useShareLimit(); + const { data: queueAnalysis } = useDepositQueueBatches( + calculateAndSelectByOperator(nodeOperatorId), + ); + + const curveId = useCurrentCurveId(); + const { data: queueConfig } = useCurveParameters( + curveId, + (params) => params.queueConfig, + ); + + const form = useFormContext(); + const submittingCount = form?.getValues('depositData')?.length; + + const submittingAllocation = calculatePriorityPlacement( + operatorInfo, + queueConfig, + submittingCount, + ); + + return { + nodeOperatorId, + operatorInfo, + shareLimit, + queueAnalysis, + submittingAllocation, + isLoading: !shareLimit, + }; +}; + +export const isMultiQueue = ( + queueAnalysis: DepositQueueAnalysis | undefined, +): queueAnalysis is DepositQueueAnalysis => { + return Boolean( + queueAnalysis && + queueAnalysis.queueAnalysis && + queueAnalysis.queueAnalysis.some((q) => q.totalKeysInQueue > 0n), + ); +}; diff --git a/features/view-keys/deposit-queue/hooks/use-single-queue.ts b/features/view-keys/deposit-queue/hooks/use-single-queue.ts new file mode 100644 index 000000000..ac3ff9873 --- /dev/null +++ b/features/view-keys/deposit-queue/hooks/use-single-queue.ts @@ -0,0 +1,71 @@ +import type { + SubmittingAllocation, + QueueGraphData, + ShareLimit, +} from './enhanced-types'; +import { + calculateGraphBounds, + calculateLimitOffset, + calculateSegmentSize, +} from './graph-calculations'; + +export const createSingleQueueVisualization = ( + shareLimit: ShareLimit, + submittingAllocation: SubmittingAllocation | undefined, + fullView: boolean, +): QueueGraphData => { + const { active, queue, capacity, activeLeft } = shareLimit; + const added = submittingAllocation?.keysCount || 0n; + + // Calculate graph bounds and coordinates + const bounds = calculateGraphBounds({ + active, + queue, + capacity, + added, + fullView, + }); + + // Calculate segment sizes + const activeSize = calculateSegmentSize(active, 0n, bounds); + + const addedSize = calculateSegmentSize(added, queue + active, bounds); + + const limitOffset = calculateLimitOffset(capacity, bounds); + + // Calculate queue segments + const queueUnderLimit = + activeLeft > 0n ? (queue < activeLeft ? queue : activeLeft) : 0n; + const queueOverLimit = queue - queueUnderLimit; + + const queueUnderLimitSize = calculateSegmentSize( + queueUnderLimit, + active, + bounds, + ); + + const queueOverLimitSize = calculateSegmentSize( + queueOverLimit, + queueUnderLimit + active, + bounds, + ); + + return { + parts: [ + { type: 'active', width: activeSize, keysCount: active }, + { type: 'queue', width: queueUnderLimitSize, keysCount: queueUnderLimit }, + { + type: 'queueOverLimit', + width: queueOverLimitSize, + keysCount: queueOverLimit, + }, + { type: 'added', width: addedSize, keysCount: added }, + ], + limit: { + offset: limitOffset, + keysCount: capacity, + }, + farAway: bounds.farAway, + submittingKeysCount: submittingAllocation?.keysCount, + }; +}; diff --git a/features/view-keys/deposit-queue/hover-provider.tsx b/features/view-keys/deposit-queue/hover-provider.tsx index c5523f338..65c04cfb0 100644 --- a/features/view-keys/deposit-queue/hover-provider.tsx +++ b/features/view-keys/deposit-queue/hover-provider.tsx @@ -8,25 +8,34 @@ import { import invariant from 'tiny-invariant'; import { GraphPart } from './types'; -export type HoverContextType = { +export type GraphInteractionContextType = { hover?: GraphPart; setHover: (hover?: GraphPart) => void; + fullView: boolean; + setFullView: (fullView: boolean) => void; }; -const HoverContext = createContext({} as HoverContextType); +const GraphInteractionContext = createContext( + {} as GraphInteractionContextType, +); -export const HoverProvider: FC = ({ children }) => { +export const GraphInteractionProvider: FC = ({ + children, +}) => { const [hover, setHover] = useState(); + const [fullView, setFullView] = useState(false); return ( - + {children} - + ); }; -export const useHover = () => { - const value = useContext(HoverContext); - invariant(value, 'useHover was used outside the provider'); +export const useGraphInteraction = () => { + const value = useContext(GraphInteractionContext); + invariant(value, 'useGraphInteraction was used outside the provider'); return value; }; diff --git a/features/view-keys/deposit-queue/legend.tsx b/features/view-keys/deposit-queue/legend.tsx index 5308a4ef8..514904f98 100644 --- a/features/view-keys/deposit-queue/legend.tsx +++ b/features/view-keys/deposit-queue/legend.tsx @@ -1,23 +1,18 @@ import { FC, useCallback } from 'react'; import { Stack } from 'shared/components'; -import { useHover } from './hover-provider'; +import { useGraphInteraction } from './hover-provider'; import { ChipStyle, CircleStyle, LegendStyle, PartStyle } from './style'; +import { getPriorityName } from './get-priority-name'; import { GraphPart } from './types'; type LegendProps = { type: GraphPart; - title: string; - count?: string; + keysCount?: number | bigint; hide?: boolean; }; -export const Legend: FC = ({ - type, - title, - count, - hide = false, -}) => { - const { setHover } = useHover(); +export const Legend: FC = ({ type, keysCount, hide = false }) => { + const { setHover } = useGraphInteraction(); const handleHover = useCallback(() => { setHover(type); @@ -30,6 +25,12 @@ export const Legend: FC = ({ return null; } + const title = getPriorityName(type); + + if (!keysCount && !['limit', 'active'].includes(type)) { + return null; + } + return ( @@ -37,10 +38,8 @@ export const Legend: FC = ({ {title} - {(count !== undefined && ( - - {count} - + {(keysCount !== undefined && ( + {keysCount.toString()} )) || null} diff --git a/features/view-keys/deposit-queue/line-wrapper.tsx b/features/view-keys/deposit-queue/line-wrapper.tsx new file mode 100644 index 000000000..c4db83b05 --- /dev/null +++ b/features/view-keys/deposit-queue/line-wrapper.tsx @@ -0,0 +1,18 @@ +import { FC, PropsWithChildren } from 'react'; +import { useGraphInteraction } from './hover-provider'; +import { FarStyle, WrapperStyle } from './style'; + +type Props = { farAway: boolean }; + +export const LineWrapper: FC> = ({ + children, + farAway, +}) => { + const { setFullView } = useGraphInteraction(); + return ( + setFullView(false)}> + + ); +}; diff --git a/features/view-keys/deposit-queue/part.tsx b/features/view-keys/deposit-queue/part.tsx index d6f5c8c24..966dff56d 100644 --- a/features/view-keys/deposit-queue/part.tsx +++ b/features/view-keys/deposit-queue/part.tsx @@ -1,24 +1,60 @@ -import { FC } from 'react'; -import { useHover } from './hover-provider'; -import { GraphPart } from './types'; +import { Tooltip } from 'shared/components'; +import { FC, useCallback } from 'react'; +import { useGraphInteraction } from './hover-provider'; import { PartStyle } from './style'; +import { BatchMetadata, GraphPart } from './types'; +import { BatchTooltipContent } from './batch-tooltip-content'; +import { AddedTooltipContent } from './added-tooltip-content'; type PartProps = { type: GraphPart; - size?: number; + width?: number; offset?: number; -} & React.HTMLAttributes; + metadata?: BatchMetadata; +}; + +export const Part: FC = ({ type, width, offset, metadata }) => { + const { hover, setFullView } = useGraphInteraction(); + + const onMouseEnter = useCallback(() => { + setFullView(true); + }, [setFullView]); -export const Part: FC = ({ type, size, offset, ...props }) => { - const { hover } = useHover(); + if (!width && type !== 'limit') { + return null; + } - return ( + const part = ( ); + + if (type === 'batch' && metadata) { + return ( + } + placement="top" + > + {part} + + ); + } + + if (type === 'added' && metadata) { + return ( + } + placement="top" + > + {part} + + ); + } + + return part; }; diff --git a/features/view-keys/deposit-queue/style.ts b/features/view-keys/deposit-queue/style.ts index fe109270a..b15f94667 100644 --- a/features/view-keys/deposit-queue/style.ts +++ b/features/view-keys/deposit-queue/style.ts @@ -3,6 +3,61 @@ import { StackStyle } from 'shared/components'; import styled, { css } from 'styled-components'; import { GraphPart } from './types'; +const COLOR_VARIANTS = { + active: css` + color: #53ba95; + `, + queue: css` + color: #00a3ff; + `, + priority0: css` + color: #00cfff; + `, + priority1: css` + color: #007fff; + `, + priority2: css` + color: #0046ff; + `, + priority3: css` + color: #002db3; + `, + priority4: css` + color: #6e0eff; + `, + priority5: css` + color: #c747ff; + `, + queueOverLimit: css` + color: #81d1ff; + `, + priority0OverLimit: css` + color: #66e7ff; + `, + priority1OverLimit: css` + color: #66bfff; + `, + priority2OverLimit: css` + color: #668aff; + `, + priority3OverLimit: css` + color: #6685cc; + `, + priority4OverLimit: css` + color: #9966ff; + `, + priority5OverLimit: css` + color: #da85ff; + `, + batch: css` + color: #ffa276; + `, + added: css` + color: #ff8d47ff; + `, + limit: css``, +} as const; + export const WrapperStyle = styled.div` position: relative; `; @@ -33,77 +88,86 @@ export const LineStyle = styled.div` white-space: nowrap; `; +const linearGradient = css` + --part-color-1: currentColor; + --part-color-2: color-mix(in srgb, var(--part-color-1) 85%, white 15%); + + background: repeating-linear-gradient( + 120deg, + var(--part-color-1), + var(--part-color-1) 4px, + var(--part-color-2) 4px, + var(--part-color-2) 8px + ) + 0px fixed; +`; + type PartProps = { $type: GraphPart; - $size?: number; + $width?: number; $offset?: number; $fade?: boolean; }; -const linearGradient = ( - color1: string, - color2: string, - angle = 120, - w1 = 4, - w2 = 4, -) => css` - background: repeating-linear-gradient( - ${angle}deg, - ${color1}, - ${color1} ${w1}px, - ${color2} ${w1}px, - ${color2} ${w1 + w2}px - ); - background-attachment: fixed; - background-position-x: 0px; -`; - -const PART_VARIANTS = { - active: css` - background: #53ba95; - `, - queued: css` - ${linearGradient('#00a3ff', '#26b1ff')} - `, - queuedOverLimit: css` - ${linearGradient('#81d1ff', '#94d8ff')} - `, - yourQueued: css` - position: absolute; - left: ${({ $offset }) => $offset}%; - - ${linearGradient('#ffa276', '#ffb695')} - `, - added: css` - background: #f17ecb; - `, - limit: css` - position: absolute; - width: 2px; - left: calc(${({ $offset = 50 }) => $offset}% - 1px); - - top: -40%; - height: 180%; - - ${linearGradient('var(--lido-color-text)', 'transparent', 0, 5, 3)} - background-attachment: initial; - - mix-blend-mode: ${({ theme }) => - theme.name === ThemeName.light ? 'multiply' : 'plus-lighter'}; - `, +const getPartVariant = (type: GraphPart) => { + switch (type) { + case 'active': + case 'added': + return css` + background: currentColor; + `; + case 'batch': + return css` + position: absolute; + left: ${({ $offset }) => $offset}%; + + ${linearGradient} + `; + case 'limit': + return css` + position: absolute; + z-index: 1; + width: 2px; + left: ${({ $offset = 50 }) => + !$offset ? '1px' : `calc(${$offset}% - 1px)`}; + + top: -40%; + height: 180%; + + --part-color-1: var(--lido-color-text); + --part-color-2: transparent; + background: repeating-linear-gradient( + 0deg, + var(--part-color-1), + var(--part-color-1) 5px, + var(--part-color-2) 5px, + var(--part-color-2) 8px + ) + 0px; + + mix-blend-mode: ${({ theme }) => + theme.name === ThemeName.light ? 'multiply' : 'plus-lighter'}; + `; + default: + return css` + ${linearGradient} + `; + } }; export const PartStyle = styled.div` display: inline-block; height: 100%; - width: ${({ $size = 100 }) => $size}%; + width: ${({ $width = 100 }) => $width}%; opacity: ${({ $fade }) => ($fade ? '0.2' : '1')}; transition: opacity 0.25s ease-in-out, left 0.25s ease-in-out, width 0.25s ease-in-out; + position: relative; - ${(props) => PART_VARIANTS[props.$type]} + ${({ $type }) => COLOR_VARIANTS[$type] ?? ''} + ${({ $type }) => getPartVariant($type)} `; export const CircleStyle = styled(LineStyle)` @@ -119,26 +183,10 @@ export const LegendsStyle = styled(StackStyle)` gap: 12px 24px; `; -const CHIP_VARIANTS = { - active: css` - color: #53ba95; - `, - queued: css` - color: #00a3ff; - `, - queuedOverLimit: css` - color: #81d1ff; - `, - yourQueued: css` - color: #ffa276; - `, - added: css` - color: #f17ecb; - `, - limit: css``, -}; - -export const ChipStyle = styled.div<{ $type?: GraphPart; $loading?: boolean }>` +export const ChipStyle = styled.div<{ + $type: GraphPart; + $loading?: boolean; +}>` width: fit-content; padding: 0px 4px; text-align: center; @@ -149,7 +197,7 @@ export const ChipStyle = styled.div<{ $type?: GraphPart; $loading?: boolean }>` font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; line-height: ${({ theme }) => theme.fontSizesMap.lg}px; font-weight: 700; - ${(props) => CHIP_VARIANTS[props.$type || 'active']} + ${({ $type }) => COLOR_VARIANTS[$type] ?? ''} ${({ $loading }) => $loading @@ -170,3 +218,10 @@ export const ChipStyle = styled.div<{ $type?: GraphPart; $loading?: boolean }>` ` : ''} `; + +export const TooltipContentStyle = styled(StackStyle).attrs({ + $direction: 'column', + $gap: 'xs', +})` + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; +`; diff --git a/features/view-keys/deposit-queue/types.ts b/features/view-keys/deposit-queue/types.ts index 1d194b66c..e61050bfa 100644 --- a/features/view-keys/deposit-queue/types.ts +++ b/features/view-keys/deposit-queue/types.ts @@ -1,7 +1,63 @@ export type GraphPart = | 'active' - | 'queued' - | 'queuedOverLimit' - | 'yourQueued' + | 'queue' + | 'queueOverLimit' + | 'priority0' + | 'priority1' + | 'priority2' + | 'priority3' + | 'priority4' + | 'priority5' + | 'priority0OverLimit' + | 'priority1OverLimit' + | 'priority2OverLimit' + | 'priority3OverLimit' + | 'priority4OverLimit' + | 'priority5OverLimit' | 'added' + | 'batch' | 'limit'; + +type KeysCount = { + keysCount: bigint; +}; + +export type QueuePart = { + width: number; + type: GraphPart; + metadata?: BatchMetadata; +} & KeysCount; + +export type QueueLimit = { + offset: number; +} & KeysCount; + +export type BatchMetadata = Array<{ + keysCount: bigint; + position: bigint; + priority: number; + combined?: boolean; +}>; + +export type BatchPart = { + offset: number; + width: number; + metadata: BatchMetadata; +}; + +export type OperatorQueue = { + batches: BatchPart[]; +} & KeysCount; + +export type QueueGraphData = { + limit: QueueLimit; + parts: QueuePart[]; + operator?: OperatorQueue; + farAway: boolean; + submittingKeysCount?: bigint; +}; + +export type UseDepositQueueGraphResult = { + isLoading: boolean; + data?: QueueGraphData; +}; diff --git a/features/view-keys/deposit-queue/use-deposit-queue-graph.ts b/features/view-keys/deposit-queue/use-deposit-queue-graph.ts deleted file mode 100644 index 0e14c8854..000000000 --- a/features/view-keys/deposit-queue/use-deposit-queue-graph.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { One, Zero } from '@ethersproject/constants'; -import { BigNumber } from 'ethers'; -import { useNodeOperatorId } from 'providers/node-operator-provider'; -import { useMemo } from 'react'; -import { useFormContext } from 'react-hook-form'; -import { DepositDataInputType } from 'shared/hook-form/form-controller'; -import { useCSMShareLimitInfo, useNodeOperatorInfo } from 'shared/hooks'; -import { useCSMQueueBatches } from 'shared/hooks/useCSMQueueBatches'; - -const POTENTIAL_ADDED = BigNumber.from(100); -const BACK = BigNumber.from(30); - -type Pos = { size: number; offset: number }; -const mergeBatches = (list?: Pos[]) => - list?.reduce((acc, c) => { - const last = acc.at(-1); - if (!last || last.offset + last.size < c.offset) return [...acc, c]; - last.size = c.offset + c.size - last.offset; - return acc; - }, [] as Pos[]); - -export const useDepositQueueGraph = (fullView = false) => { - const nodeOperatorId = useNodeOperatorId(); - const { data: info } = useNodeOperatorInfo(nodeOperatorId); - const hasDepositable = info?.depositableValidatorsCount; - - const { data, initialLoading } = useCSMShareLimitInfo(); - const { data: batches, initialLoading: isBatchesLoading } = - useCSMQueueBatches(hasDepositable ? nodeOperatorId : undefined); - - const form = useFormContext(); - const submitting: number | undefined = form?.getValues('depositData')?.length; - - const minSize = fullView ? 0.5 : 1; // percentage - - return useMemo(() => { - if (!data || initialLoading) return { isLoading: true }; - - const { active, queue, capacity, activeLeft } = data; - const added = submitting ? BigNumber.from(submitting) : Zero; - const isSubmitting = submitting !== undefined; - const potential = added.lt(POTENTIAL_ADDED) ? POTENTIAL_ADDED : added; - - const m0 = active.isZero() ? queue : active; - const m1 = m0.sub(BACK).isNegative() ? m0 : m0.sub(BACK); - const m2 = active.add(queue).add(potential); - const md = m2.sub(m1); - - const extraLow = !fullView && capacity.lt(m1.sub(md)); - const extraHigh = !fullView && capacity.gt(m2.add(md)); - - const l1 = fullView - ? Zero - : m1.lt(capacity) - ? m1 - : extraLow - ? m1 - : capacity; - const l2 = m2.gt(capacity) ? m2 : extraHigh ? m2 : capacity; - const ld = l2.sub(l1); - - const g1 = fullView ? 0 : extraLow ? 15 : l1.gt(potential) ? 15 : 0; - const g2 = fullView ? 95 : extraHigh ? 85 : 95; - const gd = g2 - g1; - const farAway = g1 > 0; - - const cc = (v: BigNumber) => v.sub(l1).mul(gd).div(ld).add(g1).toNumber(); - const ccc = (value: BigNumber, prev = Zero) => { - const p = prev.isZero() ? 0 : Math.max(minSize, cc(prev)); - return value.isZero() ? 0 : Math.max(minSize, cc(value.add(prev)) - p); - }; - - const queueUnderLimit = queue.lt(activeLeft) ? queue : activeLeft; - const queueOverLimit = queue.sub(queueUnderLimit); - - const activeSize = ccc(active); - const queueSize = ccc(queueUnderLimit, active); - const queueOverLimitSize = ccc(queueOverLimit, queueUnderLimit.add(active)); - const addedSize = ccc(added, queue.add(active)); - const limitOffset = extraLow ? 8 : extraHigh ? 95 : cc(capacity); - - const koef = queue - .mul(100) - .div(batches?.summ || queue) - .toNumber(); - - const yourBatches = mergeBatches( - batches?.list.map((batch) => { - const offset = batch[0].mul(koef).div(100); - let size = batch[1].mul(koef).div(100); - if (size.isZero() && !batch[1].isZero()) size = One; - - const batchProps = { - size: ccc(size, active.add(offset)), - offset: cc(offset.add(active)), - }; - - if ( - batchProps.offset + batchProps.size > - activeSize + queueSize + queueOverLimitSize - ) { - batchProps.offset = - activeSize + queueSize + queueOverLimitSize - batchProps.size; - } - - return batchProps; - }), - ); - - const depositable: string = hasDepositable - ? isBatchesLoading - ? '...' - : hasDepositable.toString() - : '0'; - - return { - isLoading: false, - graph: { - active: { - size: activeSize, - }, - queue: { - size: queueSize, - }, - queueOverLimit: { - size: queueOverLimitSize, - }, - added: { - size: addedSize, - }, - limit: { - offset: limitOffset, - }, - your: yourBatches, - farAway, - isSubmitting, - }, - values: { - active: active.toString(), - queue: queueUnderLimit.toString(), - queueOverLimit: queueOverLimit.toString(), - added: added.toString(), - limit: capacity.toString(), - your: depositable, - }, - }; - }, [ - minSize, - batches?.list, - batches?.summ, - data, - fullView, - hasDepositable, - initialLoading, - isBatchesLoading, - submitting, - ]); -}; diff --git a/features/view-keys/view-keys-page.tsx b/features/view-keys/view-keys-page.tsx index d2b277100..f852d84a2 100644 --- a/features/view-keys/view-keys-page.tsx +++ b/features/view-keys/view-keys-page.tsx @@ -3,15 +3,17 @@ import { FC } from 'react'; import { Layout } from 'shared/layout'; import { KeysPageSwitcher } from 'shared/navigate'; import { ViewKeys } from './view-keys'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { Faq } from 'shared/components'; +import { FAQ_KEYS } from 'faq'; export const ViewKeysPage: FC = () => ( + ); diff --git a/features/view-keys/view-keys-section/balance-cell.tsx b/features/view-keys/view-keys-section/balance-cell.tsx new file mode 100644 index 000000000..ae1e0cd8a --- /dev/null +++ b/features/view-keys/view-keys-section/balance-cell.tsx @@ -0,0 +1,12 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { FC } from 'react'; +import { FormatToken } from 'shared/formatters'; + +export const BalanceCell: FC<{ effectiveBalance?: bigint }> = ({ + effectiveBalance, +}) => + effectiveBalance !== undefined ? ( + + ) : ( + <>— + ); diff --git a/features/view-keys/view-keys-section/keys-table.tsx b/features/view-keys/view-keys-section/keys-table.tsx index 49b8ec785..3781f26d3 100644 --- a/features/view-keys/view-keys-section/keys-table.tsx +++ b/features/view-keys/view-keys-section/keys-table.tsx @@ -1,62 +1,85 @@ -import { Tbody, Td, Text, Th, Thead, Tr } from '@lidofinance/lido-ui'; +import { KEY_STATUS, KeyWithStatus } from '@lidofinance/lido-csm-sdk'; +import { SortButton, useTable } from 'providers/table-provider'; import { FC } from 'react'; import { - Address, - BeaconchainPubkeyLink, + PriorityChip, + Pubkey, + PubkeyLinks, Stack, - StatusChip, + KeyStatusChip, StatusComment, } from 'shared/components'; -import { KeyWithStatus, useSortedKeys } from 'shared/hooks'; -import { AddressRow, TableStyle } from './styles'; +import { useMaxPriorityKeyIndex } from 'shared/hooks'; +import { Gate } from 'shared/navigate'; +import { BalanceCell } from './balance-cell'; +import { StrikesCount } from './strikes-counts'; +import { TableStyle } from './styles'; -type Props = { - keys?: KeyWithStatus[]; -}; - -export const KeysTable: FC = ({ keys }) => { - const sortedKeys = useSortedKeys(keys); +export const KeysTable: FC = () => { + const maxPriorityKeyIndex = useMaxPriorityKeyIndex(); + const { data } = useTable(); return ( - - - # - Key - Status - Comment - - - - {sortedKeys?.map(({ key, index, statuses }) => ( - - - - {index + 1} - - - - -
          } - /> - - - + + + + Key + + + Status + + + + Strikes + + + + + Balance + + + Comment + + + + {data.map((key) => ( + + + } /> + + - {statuses.map((status) => ( - + {key.statuses.map((status) => ( + + ) : null + } + /> ))} - - - - - + + + + + + + + + + + + + + + ))} - + ); }; diff --git a/features/view-keys/view-keys-section/sort.ts b/features/view-keys/view-keys-section/sort.ts new file mode 100644 index 000000000..1a23e1e3d --- /dev/null +++ b/features/view-keys/view-keys-section/sort.ts @@ -0,0 +1,51 @@ +import { KEY_STATUS, KeyWithStatus } from '@lidofinance/lido-csm-sdk'; +import { SortCriteria, SortFunctions } from 'providers/table-provider'; +import { getArraySum } from 'utils'; + +const DEFAULT_STATUS_ORDER: KEY_STATUS[] = [ + KEY_STATUS.INVALID, + KEY_STATUS.DUPLICATED, + KEY_STATUS.UNBONDED, + KEY_STATUS.EXIT_REQUESTED, + KEY_STATUS.NON_QUEUED, + KEY_STATUS.UNCHECKED, + + KEY_STATUS.DEPOSITABLE, + KEY_STATUS.ACTIVATION_PENDING, + KEY_STATUS.ACTIVE, + KEY_STATUS.EXITING, + KEY_STATUS.WITHDRAWAL_PENDING, + KEY_STATUS.WITHDRAWN, + + KEY_STATUS.SLASHED, +]; + +const getStatusPriority = (statuses: KEY_STATUS[]): number => + DEFAULT_STATUS_ORDER.findIndex((st) => statuses.includes(st)); + +const sortByPubkey: SortCriteria = (item) => [ + item.pubkey, + item.index, +]; + +const sortByStatus: SortCriteria = (item) => [ + getStatusPriority(item.statuses), + item.index, +]; + +const sortByStrikes: SortCriteria = (item) => [ + getArraySum(item.strikes), + item.index, +]; + +const sortByBalance: SortCriteria = (item) => [ + Number(item.effectiveBalance ?? 0n), + item.index, +]; + +export const sortFunctions: SortFunctions = { + pubkey: sortByPubkey, + statuses: sortByStatus, + strikes: sortByStrikes, + effectiveBalance: sortByBalance, +}; diff --git a/features/view-keys/view-keys-section/strikes-counts.tsx b/features/view-keys/view-keys-section/strikes-counts.tsx new file mode 100644 index 000000000..18e2aa0fe --- /dev/null +++ b/features/view-keys/view-keys-section/strikes-counts.tsx @@ -0,0 +1,65 @@ +import { KeyStrikes } from '@lidofinance/lido-csm-sdk'; +import { Box, Text } from '@lidofinance/lido-ui'; +import { Tooltip } from 'shared/components'; +import { + useCurveParameters, + useNodeOperatorId, + useOperatorCurveId, +} from 'modules/web3'; +import { FC, useCallback } from 'react'; +import { useStrikeDates } from 'shared/hooks'; +import { formatDate, getArraySum } from 'utils'; + +export const StrikesCount: FC<{ strikes?: KeyStrikes }> = ({ strikes }) => { + const id = useNodeOperatorId(); + const { data: curveId } = useOperatorCurveId(id); + const { data: max } = useCurveParameters( + curveId, + (params) => params.strikesConfig.threshold, + ); + + const lastStrike = strikes?.findIndex((v) => !!v); + const getDates = useStrikeDates(undefined); + + const count = getArraySum(strikes); + const warning = max && count >= max; + + const content = ( + + 0 ? 'default' : 'secondary'} + > + {count} + + + /{max?.toString() ?? 0} + + + ); + + const getTooltip = useCallback( + (n: number) => { + const dates = getDates(n); + if (!dates) return null; + + return ( + <>Last Strike: {formatDate(dates?.receivedTimestamp, 'dd.MM.yyyy')} + ); + }, + [getDates], + ); + + return ( + <> + {lastStrike !== undefined ? ( + + {content} + + ) : ( + content + )} + + ); +}; diff --git a/features/view-keys/view-keys-section/styles.tsx b/features/view-keys/view-keys-section/styles.tsx index 2eba89784..43a99531a 100644 --- a/features/view-keys/view-keys-section/styles.tsx +++ b/features/view-keys/view-keys-section/styles.tsx @@ -1,58 +1,47 @@ -import { Block, Table } from '@lidofinance/lido-ui'; -import { StackStyle } from 'shared/components/stack/style'; +import { Table } from 'shared/components'; import styled from 'styled-components'; -export const ViewKeysBlock = styled(Block)` - display: flex; - gap: ${({ theme }) => theme.spaceMap.md}px; - flex-direction: column; -`; - export const TableStyle = styled(Table)` - margin: -32px -32px; + grid-template-columns: 5fr 4fr 1fr; - thead tr::before, - thead tr::after, - th { - border-top: none; - } + tr { + gap: 12px 32px; - th { - padding: 24px 8px 16px 8px; - min-width: 40px; + ${({ theme }) => theme.mediaQueries.md} { + grid-template-columns: 1fr; + + padding: 20px 32px; + } } - td { - padding: 12px 8px; + th:nth-child(4) { + display: none; } - th > div { - display: flex; - gap: ${({ theme }) => theme.spaceMap.xs}px; - align-items: center; + td:nth-child(4) { + grid-column: 1 / -1; - svg { - width: 16px; + &:empty { + display: none; } } - td { - border-bottom: none; + td:empty, + td:has(> span:empty) { + display: none; } - td:last-child { - max-width: 200px; - } + td:nth-child(3) { + justify-self: center; - td:nth-child(2) { - min-width: max-content; + ${({ theme }) => theme.mediaQueries.md} { + justify-self: start; + } } - tbody tr:nth-child(odd) { - background-color: var(--lido-color-accentControlBg); + thead { + ${({ theme }) => theme.mediaQueries.md} { + display: none; + } } `; - -export const AddressRow = styled(StackStyle).attrs({ $gap: 'xs' })` - align-items: center; -`; diff --git a/features/view-keys/view-keys-section/view-keys-section.tsx b/features/view-keys/view-keys-section/view-keys-section.tsx index 4a9eef542..68affcffb 100644 --- a/features/view-keys/view-keys-section/view-keys-section.tsx +++ b/features/view-keys/view-keys-section/view-keys-section.tsx @@ -1,20 +1,33 @@ +import { useNodeOperatorId, useOperatorKeysWithStatus } from 'modules/web3'; +import { TablePagination, TableProvider } from 'providers/table-provider'; import { FC } from 'react'; -import { WhenLoaded } from 'shared/components'; -import { useKeysWithStatus } from 'shared/hooks'; +import { Block, Stack, WhenLoaded } from 'shared/components'; import { KeysTable } from './keys-table'; -import { ViewKeysBlock } from './styles'; +import { sortFunctions } from './sort'; export const ViewKeysSection: FC = () => { - const { data: keys, initialLoading: loading } = useKeysWithStatus(); + const nodeOperatorId = useNodeOperatorId(); + const { data: keys, isPending: loading } = + useOperatorKeysWithStatus(nodeOperatorId); return ( - - - - - + + + + + + + + + + ); }; diff --git a/features/view-keys/view-keys.tsx b/features/view-keys/view-keys.tsx index 8be444883..2448bafb1 100644 --- a/features/view-keys/view-keys.tsx +++ b/features/view-keys/view-keys.tsx @@ -1,8 +1,9 @@ +import { ExtraWidth } from 'shared/components'; import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; -import { useWeb3Key } from 'shared/hooks/useWeb3Key'; -import { ViewKeysSection } from './view-keys-section'; -import { ExtraWidth, Faq } from 'shared/components'; +import { useWeb3Key } from 'shared/hooks'; +import { Gate } from 'shared/navigate'; import { DepositQueue } from './deposit-queue'; +import { ViewKeysSection } from './view-keys-section'; export const ViewKeys = () => { const key = useWeb3Key(); @@ -10,11 +11,12 @@ export const ViewKeys = () => { <> - + + + - ); }; diff --git a/features/welcome/early-adoption-banner/early-adoption-banner.tsx b/features/welcome/early-adoption-banner/early-adoption-banner.tsx deleted file mode 100644 index 75ecefb70..000000000 --- a/features/welcome/early-adoption-banner/early-adoption-banner.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { FC } from 'react'; - -import { - DarkThemeProvider, - External, - LightThemeProvider, -} from '@lidofinance/lido-ui'; -import { getExternalLinks } from 'consts/external-links'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { MatomoLink, Stack } from 'shared/components'; -import { BlockStyled, Header, Heading, StyledButton } from './styles'; - -export const EarlyAdoptionBanner: FC = () => { - const links = getExternalLinks(); - - return ( - - -
          Early Adoption mode is active
          -

          - During this period, only curated community stakers are eligible to - join CSM. After the end of the period, CSM entry will be fully - permissionless. -

          -
          - {links && ( - - - - - Learn more about Early Adoption - - - - - - - See Early Adoption members list - - - - - )} -
          - ); -}; diff --git a/features/welcome/early-adoption-banner/index.ts b/features/welcome/early-adoption-banner/index.ts deleted file mode 100644 index cc08598b8..000000000 --- a/features/welcome/early-adoption-banner/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './early-adoption-banner'; diff --git a/features/welcome/early-adoption-banner/styles.tsx b/features/welcome/early-adoption-banner/styles.tsx deleted file mode 100644 index 5de472419..000000000 --- a/features/welcome/early-adoption-banner/styles.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Block, Button } from '@lidofinance/lido-ui'; -import { Stack } from 'shared/components'; -import styled from 'styled-components'; - -export const Heading = styled(Stack).attrs(() => ({ direction: 'column' }))``; - -export const Header = styled.h3` - font-size: ${({ theme }) => theme.fontSizesMap.lg}px; - line-height: ${({ theme }) => theme.fontSizesMap.xl}px; - font-weight: bold; -`; - -export const BlockStyled = styled(Block)` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spaceMap.xl}px; - - text-align: center; - color: var(--lido-color-primaryContrast); - font-size: ${({ theme }) => theme.fontSizesMap.xs}px; - line-height: ${({ theme }) => theme.fontSizesMap.lg}px; - - background: radial-gradient( - 114.67% 199.49% at 51.78% 123.98%, - #ef81f9 0%, - rgba(249, 129, 183, 0) 100% - ), - linear-gradient(97deg, #00a3ff 36.36%, #2238ff 99.58%); -`; - -export const StyledButton = styled(Button)` - min-width: max-content; - - span { - display: flex; - align-items: center; - justify-content: center; - gap: 6px; // @style - } -`; diff --git a/features/welcome/holesky-banner/holesky-banner.tsx b/features/welcome/holesky-banner/holesky-banner.tsx deleted file mode 100644 index b14421885..000000000 --- a/features/welcome/holesky-banner/holesky-banner.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { DarkThemeProvider, Text } from '@lidofinance/lido-ui'; -import { FC } from 'react'; -import { Stack } from 'shared/components'; -import { StyledAccordion } from './style'; - -export const HoleskyBanner: FC<{ open?: boolean }> = ({ open }) => { - return ( - - - - CSM is paused on Holesky - - - CSM is transitioning from the Holesky testnet to the Hoodi - testnet, and its operations on Holesky have been paused. - - - } - > - <> - - This means that uploading new keys is currently not possible, but - Node Operator stats can be viewed. - - - This update affects only CSM on Holesky testnet — CSM on Mainnet - remains fully operational. - - - Stay tuned for more details on the Hoodi testnet launch! - - - - - ); -}; diff --git a/features/welcome/holesky-banner/index.ts b/features/welcome/holesky-banner/index.ts deleted file mode 100644 index 07dbb04b3..000000000 --- a/features/welcome/holesky-banner/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './holesky-banner'; diff --git a/features/welcome/holesky-banner/style.ts b/features/welcome/holesky-banner/style.ts deleted file mode 100644 index 5e687c5bf..000000000 --- a/features/welcome/holesky-banner/style.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Accordion } from '@lidofinance/lido-ui'; -import styled from 'styled-components'; - -export const StyledAccordion = styled(Accordion)` - --first-color: #bfdbfe; - --second-color: #ccfbf1; - - background: radial-gradient( - 1435.85% 196.07% at 95.46% -44.7%, - rgba(34, 56, 255, 0.8) 0%, - rgba(235, 0, 255, 0.4) 100% - ), - linear-gradient(102deg, #bae6fd -8.89%, #93c5fd 105.62%); - - > div + div p { - margin-bottom: 0.5em; - } -`; diff --git a/features/welcome/landing/index.ts b/features/welcome/landing/index.ts new file mode 100644 index 000000000..3c3d7b501 --- /dev/null +++ b/features/welcome/landing/index.ts @@ -0,0 +1 @@ +export * from './landing-block'; diff --git a/features/welcome/landing/landing-block.tsx b/features/welcome/landing/landing-block.tsx new file mode 100644 index 000000000..9f9c3dd11 --- /dev/null +++ b/features/welcome/landing/landing-block.tsx @@ -0,0 +1,18 @@ +import { DarkThemeProvider } from '@lidofinance/lido-ui'; +import { getExternalLinks } from 'consts'; +import { moduleMeta } from 'consts/module'; +import { FC } from 'react'; +import { MatomoLink } from 'shared/components'; +import { ArrowStyled, BlockStyled } from './styles'; + +const { landing } = getExternalLinks(); + +export const LandingBlock: FC = () => ( + + + + Learn more about {moduleMeta.shortTitle} + + + +); diff --git a/features/welcome/landing/styles.ts b/features/welcome/landing/styles.ts new file mode 100644 index 000000000..819a10a17 --- /dev/null +++ b/features/welcome/landing/styles.ts @@ -0,0 +1,41 @@ +import { ArrowBack } from '@lidofinance/lido-ui'; +import { HatBlock } from 'shared/components'; +import styled from 'styled-components'; + +export const BlockStyled = styled(HatBlock)` + padding: 12px 32px 42px; + + background: linear-gradient( + 289deg, + #ef81f9 17.83%, + rgba(38, 0, 255, 0) 133.66% + ), + radial-gradient( + 711.17% 355.33% at 142.36% -215.44%, + #9995ff 0%, + #2238ff 100% + ); + + display: flex; + justify-content: center; + + a { + font-size: ${({ theme }) => theme.fontSizesMap.xs}px; + line-height: ${({ theme }) => theme.fontSizesMap.xl}px; + font-weight: 700; + color: var(--lido-color-secondary); + + &:hover { + color: var(--lido-color-secondaryHover); + } + + &:visited { + color: var(--lido-color-secondary); + } + } +`; + +export const ArrowStyled = styled(ArrowBack)` + transform: rotate(180deg); + margin-left: 8px; +`; diff --git a/features/welcome/maintenance-banner/maintenance-banner.tsx b/features/welcome/maintenance-banner/maintenance-banner.tsx index e0e30b724..1c97818dc 100644 --- a/features/welcome/maintenance-banner/maintenance-banner.tsx +++ b/features/welcome/maintenance-banner/maintenance-banner.tsx @@ -1,11 +1,12 @@ import { FC } from 'react'; import { BannerHeader, BlockStyled } from './styles'; +import { moduleMeta } from 'consts'; export const MaintenanceBanner: FC = () => { return ( - CSM is under maintenance + {moduleMeta.shortTitle} is under maintenance

          Come back a while

          ); diff --git a/features/welcome/maintenance-page.tsx b/features/welcome/maintenance-page.tsx index b37bca129..fcdd6a8f2 100644 --- a/features/welcome/maintenance-page.tsx +++ b/features/welcome/maintenance-page.tsx @@ -1,20 +1,13 @@ import { FC } from 'react'; - +import { WelcomeSection } from 'shared/components'; import { Layout } from 'shared/layout'; import { MaintenanceBanner } from './maintenance-banner'; -import { WelcomeSection } from './welcome-section'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { TryCSM } from './try-csm'; +import { TryOtherNetwork } from './try-other-network'; -export const MaintenancePage: FC = () => { - return ( - - - - - - ); -}; +export const MaintenancePage: FC = () => ( + + + + + +); diff --git a/features/welcome/navigate-cm-v1/index.ts b/features/welcome/navigate-cm-v1/index.ts new file mode 100644 index 000000000..ca3038cee --- /dev/null +++ b/features/welcome/navigate-cm-v1/index.ts @@ -0,0 +1 @@ +export * from './navigate-cm-v1'; diff --git a/features/welcome/navigate-cm-v1/navigate-cm-v1.tsx b/features/welcome/navigate-cm-v1/navigate-cm-v1.tsx new file mode 100644 index 000000000..544f7392b --- /dev/null +++ b/features/welcome/navigate-cm-v1/navigate-cm-v1.tsx @@ -0,0 +1,38 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { MatomoLink } from 'shared/components/matomo-link/matomo-link'; +import { useExternalLinks } from 'shared/hooks'; +import { StyledBlock, StyledStack } from './styles'; + +export const NavigateCMv1: FC = () => { + const { operatorsWidget } = useExternalLinks(); + const { host } = new URL(operatorsWidget); + return ( + + + + Navigate to CM v1 + + + + + + + If you are looking for the CM v1 interface, please navigate to{' '} + + {host} + + . + + + ); +}; diff --git a/features/welcome/navigate-cm-v1/styles.ts b/features/welcome/navigate-cm-v1/styles.ts new file mode 100644 index 000000000..daa5106b3 --- /dev/null +++ b/features/welcome/navigate-cm-v1/styles.ts @@ -0,0 +1,23 @@ +import { Block } from '@lidofinance/lido-ui'; +import { StackStyle } from 'shared/components/stack/style'; +import styled from 'styled-components'; + +export const StyledBlock = styled(Block)` + display: flex; + flex-direction: column; + justify-content: center; + + gap: ${({ theme }) => theme.spaceMap.md}px; +`; + +export const StyledStack = styled(StackStyle).attrs({ + $justify: 'space-between', +})` + @media screen and (max-width: 540px) { + flex-wrap: wrap; + + & > * { + flex-grow: 1; + } + } +`; diff --git a/features/welcome/try-csm/index.ts b/features/welcome/try-csm/index.ts deleted file mode 100644 index f467369b0..000000000 --- a/features/welcome/try-csm/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './try-csm'; diff --git a/features/welcome/try-csm/styles.ts b/features/welcome/try-csm/styles.ts deleted file mode 100644 index 1e8d52a02..000000000 --- a/features/welcome/try-csm/styles.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Block } from '@lidofinance/lido-ui'; -import { StackStyle } from 'shared/components/stack/style'; -import styled from 'styled-components'; - -export const StyledBlock = styled(Block)` - display: flex; - flex-direction: column; - justify-content: center; - - gap: ${({ theme }) => theme.spaceMap.md}px; -`; - -export const StyledStack = styled(StackStyle).attrs({ $spaceBetween: true })` - @media screen and (max-width: 540px) { - flex-wrap: wrap; - - & > * { - flex-grow: 1; - } - } -`; diff --git a/features/welcome/try-csm/try-csm.tsx b/features/welcome/try-csm/try-csm.tsx deleted file mode 100644 index a092b7b1c..000000000 --- a/features/welcome/try-csm/try-csm.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { Button, Text } from '@lidofinance/lido-ui'; -import { getConfig } from 'config'; -import { CHAINS } from 'consts/chains'; -import { CSM_MAINNET_LINK, CSM_TESTNET_LINK } from 'consts/external-links'; -import { FC } from 'react'; -import { MatomoLink } from 'shared/components'; -import { StyledBlock, StyledStack } from './styles'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; - -const { defaultChain } = getConfig(); - -export const TryCSM: FC = () => { - const isMainnet = defaultChain === CHAINS.Mainnet; - - if (isMainnet) - return ( - - - - Try CSM on Holesky - - - - - - - CSM uses Holesky as a testnet playground for those who want to try the - module in action in a test environment. - - - ); - - return ( - - - - Try CSM on Mainnet - - - - - - - ); -}; diff --git a/features/welcome/try-other-network/index.ts b/features/welcome/try-other-network/index.ts new file mode 100644 index 000000000..37196d727 --- /dev/null +++ b/features/welcome/try-other-network/index.ts @@ -0,0 +1 @@ +export { TryOtherNetwork } from './try-other-network'; diff --git a/features/welcome/try-other-network/styles.ts b/features/welcome/try-other-network/styles.ts new file mode 100644 index 000000000..daa5106b3 --- /dev/null +++ b/features/welcome/try-other-network/styles.ts @@ -0,0 +1,23 @@ +import { Block } from '@lidofinance/lido-ui'; +import { StackStyle } from 'shared/components/stack/style'; +import styled from 'styled-components'; + +export const StyledBlock = styled(Block)` + display: flex; + flex-direction: column; + justify-content: center; + + gap: ${({ theme }) => theme.spaceMap.md}px; +`; + +export const StyledStack = styled(StackStyle).attrs({ + $justify: 'space-between', +})` + @media screen and (max-width: 540px) { + flex-wrap: wrap; + + & > * { + flex-grow: 1; + } + } +`; diff --git a/features/welcome/try-other-network/try-cm-mainnet.tsx b/features/welcome/try-other-network/try-cm-mainnet.tsx new file mode 100644 index 000000000..43689432f --- /dev/null +++ b/features/welcome/try-other-network/try-cm-mainnet.tsx @@ -0,0 +1,26 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { CM_MAINNET_LINK } from 'consts/external-links'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { FC } from 'react'; +import { MatomoLink } from 'shared/components/matomo-link/matomo-link'; +import { StyledBlock, StyledStack } from './styles'; + +export const TryCmMainnet: FC = () => { + return ( + + + + Navigate to CM on Mainnet + + + + + + + ); +}; diff --git a/features/welcome/try-other-network/try-cm-testnet.tsx b/features/welcome/try-other-network/try-cm-testnet.tsx new file mode 100644 index 000000000..62558668d --- /dev/null +++ b/features/welcome/try-other-network/try-cm-testnet.tsx @@ -0,0 +1,30 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { CM_MAINNET_LINK } from 'consts/external-links'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { FC } from 'react'; +import { MatomoLink } from 'shared/components/matomo-link/matomo-link'; +import { StyledBlock, StyledStack } from './styles'; + +export const TryCmTestnet: FC = () => { + return ( + + + + Navigate to CM on Hoodi + + + + + + + CM uses Hoodi as a testnet playground for those who want to try the + module in action in a test environment + + + ); +}; diff --git a/features/welcome/try-other-network/try-csm-mainnet.tsx b/features/welcome/try-other-network/try-csm-mainnet.tsx new file mode 100644 index 000000000..60323a59a --- /dev/null +++ b/features/welcome/try-other-network/try-csm-mainnet.tsx @@ -0,0 +1,26 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { CSM_MAINNET_LINK } from 'consts/external-links'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { FC } from 'react'; +import { MatomoLink } from 'shared/components/matomo-link/matomo-link'; +import { StyledBlock, StyledStack } from './styles'; + +export const TryCsmMainnet: FC = () => { + return ( + + + + Try CSM on Mainnet + + + + + + + ); +}; diff --git a/features/welcome/try-other-network/try-csm-testnet.tsx b/features/welcome/try-other-network/try-csm-testnet.tsx new file mode 100644 index 000000000..0d303162c --- /dev/null +++ b/features/welcome/try-other-network/try-csm-testnet.tsx @@ -0,0 +1,30 @@ +import { Button, Text } from '@lidofinance/lido-ui'; +import { CSM_TESTNET_LINK } from 'consts/external-links'; +import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; +import { MatomoLink } from 'shared/components/matomo-link/matomo-link'; +import { StyledBlock, StyledStack } from './styles'; +import { FC } from 'react'; + +export const TryCsmTestnet: FC = () => { + return ( + + + + Try CSM on Hoodi + + + + + + + CSM uses Hoodi as a testnet playground for those who want to try the + module in action in a test environment + + + ); +}; diff --git a/features/welcome/try-other-network/try-other-network.tsx b/features/welcome/try-other-network/try-other-network.tsx new file mode 100644 index 000000000..921958cac --- /dev/null +++ b/features/welcome/try-other-network/try-other-network.tsx @@ -0,0 +1,16 @@ +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; +import { getConfig } from 'config'; +import { isModuleCM } from 'consts/module'; +import { FC } from 'react'; +import { TryCsmMainnet } from './try-csm-mainnet'; +import { TryCsmTestnet } from './try-csm-testnet'; + +const { defaultChain } = getConfig(); + +export const TryOtherNetwork: FC = () => { + const isMainnet = defaultChain === CHAINS.Mainnet; + + if (isModuleCM) return null; // CM is not available on mainnet networks yet + + return isMainnet ? : ; +}; diff --git a/features/welcome/welcome-page.tsx b/features/welcome/welcome-page.tsx index 64fdefa2a..3930af0bd 100644 --- a/features/welcome/welcome-page.tsx +++ b/features/welcome/welcome-page.tsx @@ -2,14 +2,16 @@ import { FC } from 'react'; import { Layout } from 'shared/layout'; import { Welcome } from './welcome'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { TryCSM } from './try-csm'; +import { TryOtherNetwork } from './try-other-network'; +import { NavigateCMv1 } from './navigate-cm-v1'; +import { isModuleCM } from 'consts'; export const WelcomePage: FC = () => { return ( - + - + + {isModuleCM && } ); }; diff --git a/features/welcome/welcome-section/index.ts b/features/welcome/welcome-section/index.ts deleted file mode 100644 index b59bbc6d7..000000000 --- a/features/welcome/welcome-section/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './welcome-section'; diff --git a/features/welcome/welcome-section/styles.ts b/features/welcome/welcome-section/styles.ts deleted file mode 100644 index 1d3f4de0a..000000000 --- a/features/welcome/welcome-section/styles.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Block, ThemeName } from '@lidofinance/lido-ui'; -import styled from 'styled-components'; - -import LogoDark from 'assets/csm-dark.png'; -import LogoLight from 'assets/csm-light.png'; - -export const Header = styled.h1` - font-size: 48px; // @style - line-height: 52px; // @style - font-weight: 600; -`; - -export const Heading = styled.header` - display: flex; - flex-direction: column; - gap: 0; - padding-inline: 32px; - - line-height: 52px; - color: var(--lido-color-text); - - @media screen and (max-width: 540px) { - padding-inline: 0; - } -`; - -export const ContentWrapper = styled.div` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spaceMap.md}px; - - text-align: left; - color: var(--lido-color-text); - font-size: ${({ theme }) => theme.fontSizesMap.xs}px; - line-height: ${({ theme }) => theme.fontSizesMap.xl}px; -`; - -export const BlockStyled = styled(Block)` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spaceMap.xxl}px; - border-radius: 32px; // @style - - text-align: center; - color: var(--lido-color-text); - font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; - line-height: ${({ theme }) => theme.fontSizesMap.lg}px; -`; - -export const CSMLogo = styled.img.attrs(({ theme }) => ({ - alt: '', - src: theme.name === ThemeName.light ? LogoLight.src : LogoDark.src, -}))` - width: 55%; - display: flex; - align-self: center; - margin-bottom: -4%; -`; diff --git a/features/welcome/welcome-section/welcome-section.tsx b/features/welcome/welcome-section/welcome-section.tsx deleted file mode 100644 index 07c07c5fe..000000000 --- a/features/welcome/welcome-section/welcome-section.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { FC, PropsWithChildren } from 'react'; - -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { MatomoLink } from 'shared/components'; -import { - BlockStyled, - CSMLogo, - ContentWrapper, - Header, - Heading, -} from './styles'; - -export const WelcomeSection: FC = ({ children }) => ( - - - -
          Community Staking Module
          -
          - -

          - The Community Staking Module (CSM) is a permissionless staking module - aimed at attracting community stakers to participate in the Lido on - Ethereum protocol as Node Operators. For a detailed description of the - module, follow the{' '} - - link - - . -

          -
          - {children} -
          -); diff --git a/features/welcome/welcome.tsx b/features/welcome/welcome.tsx index 5acdd4339..8bfbea8dc 100644 --- a/features/welcome/welcome.tsx +++ b/features/welcome/welcome.tsx @@ -1,48 +1,47 @@ import { FC } from 'react'; import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; -import { Stack } from 'shared/components'; -import { useAccount } from 'shared/hooks'; -import { useCsmPaused, useCsmPublicRelease } from 'shared/hooks/useCsmStatus'; -import { Connect, Fallback } from 'shared/wallet'; -import { EarlyAdoptionBanner } from './early-adoption-banner'; -import { WelcomeSection } from './welcome-section'; +import { Stack, WelcomeSection } from 'shared/components'; +import { Connect } from 'shared/wallet'; import styled from 'styled-components'; -import { HoleskyBanner } from './holesky-banner'; -import { getConfig } from 'config'; -import { CHAINS } from 'consts/chains'; - -const { defaultChain } = getConfig(); +import { LandingBlock } from './landing'; +import { isModuleCSM } from 'consts'; export const Welcome: FC = () => { - const { active, isConnected } = useAccount(); - const { data: isPublicRelease } = useCsmPublicRelease(); - const { data: paused } = useCsmPaused(); - - const isWrongChain = isConnected && !active; - return ( <> - {defaultChain === CHAINS.Holesky && paused && } - {isWrongChain && } + {isModuleCSM && } - - - I am a Node Operator - + {isModuleCSM ? ( + + + I am a Node Operator + + + Become a Node Operator + + + ) : ( - Become a Node Operator + Connect wallet - + )} - {!isPublicRelease && !paused && } ); }; diff --git a/features/wrapped/components/backgrounds.tsx b/features/wrapped/components/backgrounds.tsx new file mode 100644 index 000000000..5eeae5f5d --- /dev/null +++ b/features/wrapped/components/backgrounds.tsx @@ -0,0 +1,21 @@ +import styled from 'styled-components'; + +import bgOutro from 'assets/wrapped/outro.svg'; +import { FC } from 'react'; + +export type SlideVariant = 'outro' | 'wrap'; + +const SlideImage = styled.img` + position: absolute; + inset: 0; + pointer-events: none; + z-index: 0; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center top; +`; + +export const Background: FC = () => { + return ; +}; diff --git a/features/wrapped/components/index.ts b/features/wrapped/components/index.ts new file mode 100644 index 000000000..5e18060eb --- /dev/null +++ b/features/wrapped/components/index.ts @@ -0,0 +1,2 @@ +export { SlideDumbContainer } from './slide-container'; +export { SummaryItem } from './summary-item'; diff --git a/features/wrapped/components/slide-container.tsx b/features/wrapped/components/slide-container.tsx new file mode 100644 index 000000000..e25f4c399 --- /dev/null +++ b/features/wrapped/components/slide-container.tsx @@ -0,0 +1,23 @@ +import { DarkThemeProvider } from '@lidofinance/lido-ui'; +import { FC, PropsWithChildren } from 'react'; +import { SlideWrapper } from '../styles'; +import { Background, SlideVariant } from './backgrounds'; + +type SlideContainerProps = PropsWithChildren<{ + bg?: SlideVariant; + same?: boolean; +}>; + +export const SlideDumbContainer: FC = ({ + children, + same, +}) => { + return ( + + + + {children} + + + ); +}; diff --git a/features/wrapped/components/summary-item.tsx b/features/wrapped/components/summary-item.tsx new file mode 100644 index 000000000..2944b74ed --- /dev/null +++ b/features/wrapped/components/summary-item.tsx @@ -0,0 +1,26 @@ +import { FC, ReactNode } from 'react'; +import { Stack } from 'shared/components'; +import { SummaryStatValue, SummaryStatLabel } from '../styles'; + +type SummaryItemProps = { + value: ReactNode; + label: string; + show: boolean; + same?: boolean; +}; + +export const SummaryItem: FC = ({ + value, + label, + show, + same, +}) => { + if (show === false) return null; + + return ( + + {value} + {label} + + ); +}; diff --git a/features/wrapped/data/index.ts b/features/wrapped/data/index.ts new file mode 100644 index 000000000..fcb073fef --- /dev/null +++ b/features/wrapped/data/index.ts @@ -0,0 +1 @@ +export * from './types'; diff --git a/features/wrapped/data/types.ts b/features/wrapped/data/types.ts new file mode 100644 index 000000000..5e125d15e --- /dev/null +++ b/features/wrapped/data/types.ts @@ -0,0 +1,25 @@ +export type WrappedStats = { + totalRewardsETH: bigint; + topPerformancePercentile: number; // 0..100 + avgPerformance: bigint; // percent + bestMonthPerformance: bigint; // percent + bestMonth: string; // month name + strikesCount: number; + uploadedKeysCount: number; + queueDays: number; + activeDays: number; + proposedBlocksCount: number; + hasICS: boolean; + hasLEA: boolean; +}; + +export type WrappedStatsRaw = Omit< + WrappedStats, + 'totalRewardsETH' | 'avgPerformance' | 'bestMonthPerformance' +> & { + totalRewardsETH: string; + avgPerformance: number; + bestMonthPerformance: number; +}; + +export type WrappedStatsResponse = WrappedStatsRaw | null; diff --git a/features/wrapped/index.ts b/features/wrapped/index.ts new file mode 100644 index 000000000..ca8813f92 --- /dev/null +++ b/features/wrapped/index.ts @@ -0,0 +1 @@ +export { WrappedPage } from './wrapped-page'; diff --git a/features/wrapped/slides/index.ts b/features/wrapped/slides/index.ts new file mode 100644 index 000000000..cc3e5617b --- /dev/null +++ b/features/wrapped/slides/index.ts @@ -0,0 +1 @@ +export { SlideStats } from './slide-outro'; diff --git a/features/wrapped/slides/slide-outro.tsx b/features/wrapped/slides/slide-outro.tsx new file mode 100644 index 000000000..6128ab12a --- /dev/null +++ b/features/wrapped/slides/slide-outro.tsx @@ -0,0 +1,107 @@ +import { LightThemeProvider } from '@lidofinance/lido-ui'; +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { FormatToken } from 'shared/formatters'; +import styled, { css } from 'styled-components'; +import { formatPercent } from 'utils'; +import { SlideDumbContainer, SummaryItem } from '../components'; +import { WrappedStats } from '../data'; +import { BadgeWrapper } from '../styles'; + +const SummaryContent = styled.div<{ $same?: boolean }>` + display: flex; + flex: 1; + flex-direction: row; + gap: ${({ theme }) => theme.spaceMap.xxl}px; + justify-content: space-between; + z-index: 1; + + & > :first-child { + align-self: end; + max-width: 50%; + } + + & > :last-child { + align-self: center; + width: 190px; + } + + ${({ theme }) => theme.mediaQueries.md} { + ${({ $same }) => + !$same && + css` + flex-direction: column-reverse; + gap: 16px; + + & > :first-child { + max-width: unset; + } + + & > :last-child { + gap: 8px; + width: auto; + align-self: end; + text-align: end; + } + `} + } +`; + +export const SlideStats: FC<{ data: WrappedStats; same?: boolean }> = ({ + data, + same, +}) => { + return ( + + + + {data.hasICS && ( + + + Identified Community Staker + + + )} + + + 0} + /> + 0} + /> + 0} + /> + 0 && data.activeDays === 0} + /> + } + show={data.totalRewardsETH > 0n} + /> + 0} + /> + + + + ); +}; diff --git a/features/wrapped/styles/index.ts b/features/wrapped/styles/index.ts new file mode 100644 index 000000000..6a716a56c --- /dev/null +++ b/features/wrapped/styles/index.ts @@ -0,0 +1,2 @@ +export * from './slide'; +export * from './typography'; diff --git a/features/wrapped/styles/slide.ts b/features/wrapped/styles/slide.ts new file mode 100644 index 000000000..a4530a35b --- /dev/null +++ b/features/wrapped/styles/slide.ts @@ -0,0 +1,51 @@ +import styled, { css } from 'styled-components'; + +export const SlideWrapper = styled.div<{ $same?: boolean }>` + --gradient: linear-gradient(180deg, #5448ff 0%, #8349ff 100%); + + position: relative; + overflow: hidden; + display: flex; + flex-direction: column; + width: 100%; + min-height: 500px; + aspect-ratio: 1 / 1; + + border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px; + border: 10px solid transparent; + background: + var(--gradient) padding-box, + var(--gradient) border-box; + + color: var(--lido-color-text); + + padding: ${({ theme }) => theme.spaceMap.lg}px; + gap: ${({ theme }) => theme.spaceMap.xxl}px; + + ${({ theme }) => theme.mediaQueries.md} { + ${({ $same }) => + !$same && + css` + aspect-ratio: 2 /3; + gap: ${({ theme }) => theme.spaceMap.lg}px; + `} + } +`; + +export const SlideContent = styled.div<{ + $position?: 'center' | 'end' | 'start'; +}>` + position: relative; + z-index: 1; + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: ${({ $position = 'center' }) => $position}; + text-align: center; + gap: 46px; + + ${({ theme }) => theme.mediaQueries.md} { + gap: 30px; + } +`; diff --git a/features/wrapped/styles/typography.ts b/features/wrapped/styles/typography.ts new file mode 100644 index 000000000..3bdbd8caa --- /dev/null +++ b/features/wrapped/styles/typography.ts @@ -0,0 +1,74 @@ +import { OPERATOR_TYPE } from '@lidofinance/lido-csm-sdk'; +import { CURVE_VARIANTS } from 'shared/node-operator/curve-badge/styles'; +import styled, { css } from 'styled-components'; + +export const SlideHeading = styled.h2` + font-size: 30px; + font-weight: 700; + margin: 0; + line-height: 1.4; +`; + +export const SummaryStatValue = styled.span<{ $same?: boolean }>` + font-size: 52px; + font-weight: 700; + line-height: 1.2; + + ${({ theme }) => theme.mediaQueries.md} { + ${({ $same }) => + !$same && + css` + font-size: 42px; + `} + } +`; + +export const SummaryStatLabel = styled.span<{ $same?: boolean }>` + font-size: 18px; + font-weight: 700; + line-height: 1.5; + + ${({ theme }) => theme.mediaQueries.md} { + ${({ $same }) => + !$same && + css` + font-size: 14px; + `} + } +`; + +export const BadgeWrapper = styled.div<{ $same?: boolean }>` + position: relative; + z-index: 0; + padding: 10px 24px; + + font-weight: 700; + font-size: 16px; + letter-spacing: -0.5pt; + color: var(--lido-color-foreground); + text-align: center; + + border-radius: 14px; + border: 2px solid rgba(var(--lido-rgb-foreground), 0.8); + ${CURVE_VARIANTS[OPERATOR_TYPE.CSM_ICS]} + background-origin: border-box; + + ${({ $same }) => + $same && + css` + overflow: hidden; + `} + + &:before { + content: ''; + filter: blur(38px); + opacity: 0.8; + ${CURVE_VARIANTS[OPERATOR_TYPE.CSM_ICS]} + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + z-index: -1; + } +`; diff --git a/features/wrapped/wrapped-page.tsx b/features/wrapped/wrapped-page.tsx new file mode 100644 index 000000000..2fac6fef8 --- /dev/null +++ b/features/wrapped/wrapped-page.tsx @@ -0,0 +1,23 @@ +import { FC } from 'react'; +import { Stack } from 'shared/components'; +import { Layout } from 'shared/layout'; +import Image from 'next/image'; +import { SlideContent, SlideHeading } from './styles'; + +import bgWrap from 'assets/wrapped/wrap.png'; + +export const WrappedPage: FC = () => { + return ( + + + + See you next year! + +
          + +
          +
          +
          +
          + ); +}; diff --git a/global.d.ts b/global.d.ts index 9f0a22440..2c389cf95 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,6 +1,8 @@ interface Window { // see _document.js for definition _paq: undefined | [string, ...unknown[]][]; + + ethereum?: any; } declare module '*.svg' { @@ -26,32 +28,31 @@ declare module 'next/config' { maintenance: boolean; defaultChain: string; + rpcUrls_1: string | undefined; - rpcUrls_17000: string | undefined; - ethplorerApiKey: string | undefined; + rpcUrls_560048: string | undefined; + clApiUrls_1: string | undefined; - clApiUrls_17000: string | undefined; + clApiUrls_560048: string | undefined; - oneInchApiKey: string | undefined; + migalabsApiUrl: string | undefined; + migalabsApiToken: string | undefined; cspTrustedHosts: string | undefined; cspReportUri: string | undefined; cspReportOnly: string | undefined; - subgraphMainnet: string | undefined; - subgraphGoerli: string | undefined; - subgraphHolesky: string | undefined; - subgraphRequestTimeout: string | undefined; - rateLimit: string; rateLimitTimeFrame: string; - ethAPIBasePath: string; - rewardsBackendAPI: string | undefined; + validationAPI: string | undefined; + validationFilePath: string | undefined; }; publicRuntimeConfig: { basePath: string | undefined; developmentMode: boolean; + module: 'CSM' | 'CM'; + devnetAddresses: Record | null; }; }; diff --git a/lib/getFaq.ts b/lib/getFaq.ts deleted file mode 100644 index c31c3a3e4..000000000 --- a/lib/getFaq.ts +++ /dev/null @@ -1,88 +0,0 @@ -import matter from 'gray-matter'; -import remark from 'remark'; -import html from 'remark-html'; -import externalLinks from 'remark-external-links'; -import { getConfig } from 'config'; -import { CHAINS } from 'consts/chains'; - -export type FaqItem = { - id: string; - content: string; - title: string; - earlyAdoptionMember: boolean | null; - onlyWithReferrer: boolean | null; - anchor: string | null; -}; - -export type FaqGetter = () => Promise; - -const readFaqFile = async (id: string): Promise => { - const fileContents = await import(`faq/${id}.md`); - const matterResult = matter(fileContents.default); - - const processedContent = await remark() - .use(externalLinks, { target: '_blank', rel: ['nofollow', 'noopener'] }) - .use(html) - .process(matterResult.content); - - return { - id, - content: processedContent.toString(), - title: String(matterResult.data.title || id), - anchor: matterResult.data.anchor ?? null, - earlyAdoptionMember: matterResult.data.earlyAdoption ?? null, - onlyWithReferrer: matterResult.data.onlyWithReferrer ?? null, - }; -}; - -const { defaultChain } = getConfig(); -const isMainnet = defaultChain === CHAINS.Mainnet; - -export const readFaqFiles = async (fileNames: string[]) => { - const ids = isMainnet - ? fileNames - : fileNames.map((name) => `testnet-${name}`); - - return Promise.all(ids.map(readFaqFile)); -}; - -export const getFaqMain = () => - readFaqFiles([ - 'main-1', - 'main-2', - 'main-3', - 'main-4', - 'main-5', - 'main-6', - 'main-7', - 'main-7a', - 'main-8', - ]); - -export const getFaqKeys = () => - readFaqFiles([ - 'keys-1', - 'keys-2', - 'keys-3', - 'keys-3a', - 'keys-4', - 'keys-4a', - 'keys-5', - 'keys-6', - 'keys-7', - 'keys-8', - 'keys-9', - 'keys-10', - 'keys-13', - 'keys-11', - 'keys-12', - ]); - -export const getFaqBond = () => - readFaqFiles(['bond-1', 'bond-2', 'bond-3', 'bond-4', 'bond-5']); - -export const getFaqLocked = () => - readFaqFiles(['locked-1', 'locked-2', 'locked-3']); - -export const getFaqRoles = () => - readFaqFiles(['roles-1', 'roles-2', 'roles-3', 'roles-4', 'roles-5']); diff --git a/lib/getProps.ts b/lib/getProps.ts deleted file mode 100644 index e008f9005..000000000 --- a/lib/getProps.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { GetServerSideProps } from 'next'; -import { FaqGetter } from './getFaq'; -import { secretConfig } from 'config'; - -export const getProps = - ( - faqGetter?: FaqGetter, - options?: { continueAnyway?: boolean }, - ): GetServerSideProps => - async () => { - const { maintenance, defaultChain } = secretConfig; - - if (!options?.continueAnyway && maintenance) return { notFound: true }; - - const props = { maintenance, defaultChain }; - - return { - props: faqGetter ? { ...props, faqList: await faqGetter() } : props, - }; - }; diff --git a/mock/claim-bond/debug-panel.tsx b/mock/claim-bond/debug-panel.tsx new file mode 100644 index 000000000..e68a3cc5b --- /dev/null +++ b/mock/claim-bond/debug-panel.tsx @@ -0,0 +1,104 @@ +import { Accordion, Block, Text } from '@lidofinance/lido-ui'; +import { useClaimBondFormData } from 'features/claim-bond/claim-bond-form/context'; +import { type CLAIM_OPTION } from 'features/claim-bond/claim-bond-form/context/types'; +import { FC } from 'react'; +import styled from 'styled-components'; +import { formatEther } from 'viem'; + +const f = (v?: bigint) => formatEther(v ?? 0n); + +// Reads the derived network data straight from the form's context, so the panel +// shows exactly what the rendered form computed (no parallel re-derivation), and +// cross-checks the real availableOptions against the scenario's expectation. +export const ClaimBondDebugPanel: FC<{ + expectOptions?: CLAIM_OPTION[]; + expectEmpty?: boolean; +}> = ({ expectOptions, expectEmpty }) => { + const data = useClaimBondFormData(); + + if (!data?.bond || !data.calculation) return null; + + const { + bond, + rewards, + calculation: c, + availableOptions = [], + feeSplits = [], + isPaused, + isContract, + } = data; + + const actual = [...availableOptions].sort().join(', ') || '—'; + const expected = expectEmpty + ? '—' + : [...(expectOptions ?? [])].sort().join(', ') || '—'; + const hasExpectation = expectEmpty || !!expectOptions; + const match = !hasExpectation || actual === expected; + + return ( + + + Raw inputs & derived calculation{' '} + {match ? '✓' : '✗ options mismatch'} + + } + > + + {[ + `current: ${f(bond.current)}`, + `required (forKeys): ${f(bond.required)}`, + `locked: ${f(bond.locked)}`, + `debt: ${f(bond.debt)}`, + `pendingToSplit: ${f(bond.pendingToSplit)}`, + `delta: ${f(bond.delta)} (isInsufficient: ${bond.isInsufficient})`, + `rewards.available: ${f(rewards?.available)}`, + `feeSplits: ${ + feeSplits.map((s) => `${Number(s.share) / 100}%`).join(', ') || + '—' + }`, + '—', + `realExcess: ${f(c.realExcess)}`, + `realInsufficient: ${f(c.realInsufficient)}`, + `keysInsufficient: ${f(c.keysInsufficient)}`, + `claimableBond: ${f(c.claimableBond)}`, + `claimableBondAndRewards: ${f(c.claimableBondAndRewards)}`, + `rewardsRemainder: ${f(c.rewardsRemainder)}`, + '—', + `availableOptions: [${actual}]`, + `expectedOptions: [${expected}] ${match ? '✓' : '✗ MISMATCH'}`, + `isPaused: ${isPaused} isContract: ${isContract}`, + ].join('\n')} + + + + ); +}; + +const TestBlock = styled(Block)` + padding: 16px; +`; + +const StyledAccordion = styled(Accordion)` + & > [type='button'] { + padding: 0; + min-height: 24px; + } + & > [type='button'] + div > div { + padding: 8px 0 0; + } +`; + +const DataPre = styled.pre` + background: var(--lido-color-backgroundSecondary); + border-radius: 8px; + padding: 16px; + margin: 0; + font-family: 'Monaco', 'Menlo', monospace; + font-size: 12px; + line-height: 1.5; + white-space: pre-wrap; + word-wrap: break-word; + overflow-x: auto; +`; diff --git a/mock/claim-bond/mock-data.ts b/mock/claim-bond/mock-data.ts new file mode 100644 index 000000000..a4d65892f --- /dev/null +++ b/mock/claim-bond/mock-data.ts @@ -0,0 +1,112 @@ +import { + STETH_ROUNDING_THRESHOLD, + type BondBalance, + type FeeSplit, + type FrameInfo, + type NodeOperatorInfo, + type Rewards, + type StethPoolData, +} from '@lidofinance/lido-csm-sdk'; +import { Address, parseEther } from 'viem'; + +// Pure builders + fixtures for the claim-bond test stand. Intentionally free of +// wagmi / web3-provider imports so the scenario unit tests stay lightweight — +// the mock wagmi config lives in `./mock-wagmi`. + +const eth = (n: number) => parseEther(n.toString()); + +export const MOCK_CLAIMER: Address = + '0x1111111111111111111111111111111111111111'; +export const MOCK_REWARDS_ADDRESS: Address = + '0x2222222222222222222222222222222222222222'; + +export const MOCK_POOL_DATA: StethPoolData = { + totalPooledEther: parseEther('1000000'), + totalShares: parseEther('900000'), +}; + +// Far-future nextReport so getNextDistribution renders "on ", not "soon". +export const MOCK_FRAME: FrameInfo = { + lastReport: 1700000000, + nextReport: 4102444800, + frameDuration: 28 * 24 * 60 * 60, +}; + +export type RawBond = { + /** held bond, ether */ + current: number; + /** forKeys-only requirement, ether (matches SDK BondBalance.required) */ + forKeys: number; + locked?: number; + /** Unsettled bond debt. Real-world invariant: debt is burned from the bond on + * every touch, so debt > 0 only ever coexists with current === 0. */ + debt?: number; + pendingToSplit?: number; + /** Wei shaved off `current` to model a sub-precision forKeys deficit (e.g. 5 + * → current sits 5 wei below forKeys). The SDK clamps such share-rounding + * dust to Excess Bond 0.0; used to check no "compensate" copy leaks through. */ + deficitWei?: number; +}; + +// Mirrors calcBondBalance output semantics: required = forKeys, delta = +// |current - forKeys| clamped to 0 within STETH_ROUNDING_THRESHOLD (share- +// rounding dust), isInsufficient = current < forKeys beyond that threshold. +export const makeBond = ({ + current, + forKeys, + locked = 0, + debt = 0, + pendingToSplit = 0, + deficitWei = 0, +}: RawBond): BondBalance => { + const c = eth(current) - BigInt(deficitWei); + const required = eth(forKeys); + const raw = c - required; + const delta = raw < 0n && raw > -STETH_ROUNDING_THRESHOLD ? 0n : raw; + return { + required, + current: c, + locked: eth(locked), + debt: eth(debt), + pendingToSplit: eth(pendingToSplit), + delta: delta < 0n ? -delta : delta, + isInsufficient: delta < 0n, + }; +}; + +export const makeRewards = (available: number): Rewards => ({ + available: eth(available), + shares: eth(available), + proof: [], +}); + +// sharesPct in percent (50 → 5000n basis points); recipients are deterministic. +export const makeFeeSplits = (...sharesPct: number[]): FeeSplit[] => + sharesPct.map((pct, i) => ({ + recipient: `0x${String(i + 1) + .repeat(40) + .slice(0, 40)}`, + share: BigInt(Math.round(pct * 100)), + })); + +export const makeOperatorInfo = ({ + rewardsAddress, +}: { + rewardsAddress: Address; +}): NodeOperatorInfo => + ({ + totalAddedKeys: 10, + totalWithdrawnKeys: 0, + totalDepositedKeys: 8, + totalVettedKeys: 10, + stuckValidatorsCount: 0, + depositableValidatorsCount: 2, + targetLimit: 0, + targetLimitMode: 0, + totalExitedKeys: 0, + enqueuedCount: 0, + managerAddress: MOCK_CLAIMER, + rewardsAddress, + extendedManagerPermissions: false, + usedPriorityQueue: false, + }) as NodeOperatorInfo; diff --git a/mock/claim-bond/mock-providers.tsx b/mock/claim-bond/mock-providers.tsx new file mode 100644 index 000000000..289e22408 --- /dev/null +++ b/mock/claim-bond/mock-providers.tsx @@ -0,0 +1,146 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { useUserConfig } from 'config/user-config'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import { ClaimBondForm } from 'features/claim-bond/claim-bond-form'; +import { ClaimBondDataProvider } from 'features/claim-bond/claim-bond-form/context'; +import { + KEY_FEE_SPLITS, + KEY_OPERATOR_BALANCE, + KEY_OPERATOR_INFO, + KEY_OPERATOR_REWARDS, + KEY_STETH_POOL_DATA, + useDappStatus, +} from 'modules/web3'; +import { + NodeOperatorContext, + type NodeOperatorContextValue, +} from 'modules/web3/operator-provider/node-operator-provider'; +import { FC, PropsWithChildren, useEffect, useMemo } from 'react'; +import { hashKey } from 'utils'; +import { WagmiProvider, useConnect, useConnection } from 'wagmi'; +import { + makeBond, + makeFeeSplits, + makeOperatorInfo, + makeRewards, + MOCK_CLAIMER, + MOCK_FRAME, + MOCK_POOL_DATA, + MOCK_REWARDS_ADDRESS, +} from './mock-data'; +import { createMockWagmiConfig } from './mock-wagmi'; +import { type ClaimBondScenarioData } from './scenarios'; + +// Auto-connects the mock connector on mount so useDappStatus() reports a +// connected address. Renders nothing until connected to avoid a "no-access" +// flash and any SSR/client hydration mismatch (server render is unconnected). +const AutoConnect: FC = ({ children }) => { + const { isConnected } = useConnection(); + const { connect, connectors } = useConnect(); + useEffect(() => { + if (!isConnected && connectors[0]) { + connect({ connector: connectors[0] }); + } + }, [isConnected, connect, connectors]); + return isConnected ? <>{children} : null; +}; + +// Supplies the node operator context for the stand. Must live inside the +// WagmiProvider so it can read the actually-connected address: it mirrors that +// address onto `managerAddress` so the CLAIMER access gate passes whoever is +// connected — the mock account or a real wallet leaked in from another page +// (wagmi auto-discovers injected wallets and reconnects them from storage). +const MockOperatorProvider: FC< + PropsWithChildren<{ nodeOperatorId: bigint }> +> = ({ nodeOperatorId, children }) => { + const { address } = useDappStatus(); + + const operatorCtx: NodeOperatorContextValue = useMemo( + () => ({ + isPending: false, + nodeOperator: { + nodeOperatorId, + managerAddress: address ?? MOCK_CLAIMER, + rewardsAddress: MOCK_REWARDS_ADDRESS, + extendedManagerPermissions: false, + curveId: 0n, + }, + switchNodeOperator: () => {}, + }), + [nodeOperatorId, address], + ); + + return ( + + {children} + + ); +}; + +export const MockClaimBondProvider: FC< + PropsWithChildren<{ scenario: ClaimBondScenarioData }> +> = ({ scenario, children }) => { + const { defaultChain } = useUserConfig(); + const nodeOperatorId = BigInt(scenario.nodeOperatorId ?? 1); + + const wagmiConfig = useMemo( + () => createMockWagmiConfig(defaultChain, MOCK_CLAIMER), + [defaultChain], + ); + + const queryClient = useMemo(() => { + const client = new QueryClient({ + defaultOptions: { + queries: { + queryKeyHashFn: hashKey, + retry: false, + ...STRATEGY_IMMUTABLE, + }, + }, + }); + const idKey = { nodeOperatorId }; + client.setQueryData( + [...KEY_OPERATOR_BALANCE, idKey], + makeBond(scenario.bond), + ); + client.setQueryData( + [...KEY_OPERATOR_REWARDS, idKey], + makeRewards(scenario.rewards ?? 0), + ); + client.setQueryData( + [...KEY_OPERATOR_INFO, idKey], + makeOperatorInfo({ rewardsAddress: MOCK_REWARDS_ADDRESS }), + ); + client.setQueryData( + [...KEY_FEE_SPLITS, idKey], + scenario.feeSplits ? makeFeeSplits(...scenario.feeSplits) : [], + ); + client.setQueryData([...KEY_STETH_POOL_DATA], MOCK_POOL_DATA); + client.setQueryData(['sm-status'], { + isPausedModule: false, + isPausedAccounting: !!scenario.isPaused, + }); + client.setQueryData(['frame-info'], MOCK_FRAME); + client.setQueryData( + ['use-is-contract', MOCK_REWARDS_ADDRESS], + !!scenario.isContract, + ); + return client; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [scenario]); + + return ( + + + + + + {children && ( + {children} + )} + + + + + ); +}; diff --git a/mock/claim-bond/mock-wagmi.ts b/mock/claim-bond/mock-wagmi.ts new file mode 100644 index 000000000..6604717bd --- /dev/null +++ b/mock/claim-bond/mock-wagmi.ts @@ -0,0 +1,21 @@ +import { wagmiChainMap } from 'modules/web3/web3-provider/web3-provider'; +import { Address } from 'viem'; +import { Config, createConfig, http } from 'wagmi'; +import { mock } from 'wagmi/connectors'; + +// A self-contained wagmi config with a mock connector pre-set to `account`. +// The connector auto-connects on mount (see MockClaimBondProvider) so that +// useDappStatus() reports a connected address on the stand's default chain — +// enough to satisfy the claimBond CLAIMER access gate without a real wallet. +export const createMockWagmiConfig = ( + chainId: number, + account: Address, +): Config => { + const chain = wagmiChainMap[chainId]; + return createConfig({ + chains: [chain], + connectors: [mock({ accounts: [account] })], + transports: { [chain.id]: http() }, + ssr: false, + }); +}; diff --git a/mock/claim-bond/scenarios.ts b/mock/claim-bond/scenarios.ts new file mode 100644 index 000000000..7d4fdcc08 --- /dev/null +++ b/mock/claim-bond/scenarios.ts @@ -0,0 +1,233 @@ +import { CLAIM_OPTION } from 'features/claim-bond/claim-bond-form/context/types'; +import { type RawBond } from './mock-data'; + +export type ClaimBondScenarioData = { + nodeOperatorId?: number; + bond: RawBond; + rewards?: number; + feeSplits?: number[]; + isPaused?: boolean; + isContract?: boolean; +}; + +export type ClaimBondScenario = { + group: string; + title: string; + description: string; + data: ClaimBondScenarioData; + expectEmpty?: boolean; + expectOptions?: CLAIM_OPTION[]; +}; + +const ALL = CLAIM_OPTION.ALL_TO_RA; +const BOND = CLAIM_OPTION.BOND_TO_RA; +const R2B = CLAIM_OPTION.REWARDS_TO_BOND; + +export const testScenarios: ClaimBondScenario[] = [ + // [Basic] + { + group: 'Basic', + title: 'Excess + rewards', + description: + 'Classic state: claimable excess bond and pending rewards. All three options.', + data: { bond: { current: 34, forKeys: 32 }, rewards: 0.4 }, + expectOptions: [ALL, BOND, R2B], + }, + { + group: 'Basic', + title: 'Excess only', + description: 'Excess bond, no rewards. Only Excess Bond → Rewards Address.', + data: { bond: { current: 34, forKeys: 32 }, rewards: 0 }, + expectOptions: [BOND], + }, + { + group: 'Basic', + title: 'Rewards only (bond exact)', + description: + 'Bond exactly covers keys, rewards pending. Excess Bond option disabled.', + data: { bond: { current: 32, forKeys: 32 }, rewards: 0.4 }, + expectOptions: [ALL, R2B], + }, + { + group: 'Basic', + title: 'Nothing to claim', + description: 'No excess, no rewards. Empty state.', + data: { bond: { current: 32, forKeys: 32 }, rewards: 0 }, + expectEmpty: true, + }, + // [Insufficient] + { + group: 'Insufficient', + title: 'Insufficient, rewards > deficit', + description: + 'Rewards cover the forKeys deficit with a remainder reaching the Rewards Address.', + data: { bond: { current: 31, forKeys: 32 }, rewards: 1.5 }, + expectOptions: [ALL, R2B], + }, + { + group: 'Insufficient', + title: 'Insufficient, rewards < deficit', + description: + 'Rewards fully absorbed by the bond top-up. Nothing reaches the Rewards Address.', + data: { bond: { current: 30, forKeys: 32 }, rewards: 0.5 }, + expectOptions: [R2B], + }, + { + group: 'Insufficient', + title: 'Insufficient, no rewards', + description: 'Deficit but no rewards. Empty state.', + data: { bond: { current: 30, forKeys: 32 }, rewards: 0 }, + expectEmpty: true, + }, + // [Locked] + { + group: 'Locked', + title: 'Excess + locked + rewards', + description: + 'Excess remains above required + locked. Locked row shows with its tooltip.', + data: { bond: { current: 35, forKeys: 32, locked: 1 }, rewards: 0.4 }, + expectOptions: [ALL, BOND, R2B], + }, + { + group: 'Locked', + title: 'Locked-induced real deficit', + description: + 'forKeys covered (shows excess) but locked eats it. Rewards absorbed into bond.', + data: { bond: { current: 32.5, forKeys: 32, locked: 1 }, rewards: 0.4 }, + expectOptions: [R2B], + }, + // [Debt] — real-world invariant: debt settles against bond on every touch + // (_coverBondDebt), so debt > 0 ⟹ current == 0. INV1 (debt ⟹ no excess) then + // holds trivially. All fixtures here keep current: 0. + { + group: 'Debt', + title: 'Debt + rewards > debt + deficit', + description: + 'Rewards burn the debt and cover the deficit, remainder reaches the Rewards Address.', + data: { bond: { current: 0, forKeys: 2, debt: 1 }, rewards: 4 }, + expectOptions: [ALL, R2B], + }, + { + group: 'Debt', + title: 'Debt exceeds rewards', + description: 'Rewards partially burn debt; bond debt remaining is shown.', + data: { bond: { current: 0, forKeys: 4, debt: 2 }, rewards: 0.3 }, + expectOptions: [R2B], + }, + { + group: 'Debt', + title: 'Debt only, no rewards', + description: 'Debt alone produces nothing claimable. Empty state.', + data: { bond: { current: 0, forKeys: 32, debt: 1 }, rewards: 0 }, + expectEmpty: true, + }, + // [Splitters] + { + group: 'Splitters', + title: 'Excess + rewards + 50% splitter', + description: 'Single 50% splitter. SPLITTERS ON chip and split row appear.', + data: { bond: { current: 34, forKeys: 32 }, rewards: 1, feeSplits: [50] }, + expectOptions: [ALL, BOND, R2B], + }, + { + group: 'Splitters', + title: 'Excess + rewards + 100% (two recipients)', + description: 'Two splitters summing to 100%. Multiple split rows.', + data: { + bond: { current: 34, forKeys: 32 }, + rewards: 1, + feeSplits: [60, 40], + }, + expectOptions: [ALL, BOND, R2B], + }, + { + group: 'Splitters', + title: 'Rewards + split, no excess', + description: + 'Bond exact, rewards split with recipients. ALL option becomes split-rewards-only.', + data: { bond: { current: 32, forKeys: 32 }, rewards: 1, feeSplits: [50] }, + expectOptions: [ALL, R2B], + }, + { + group: 'Splitters', + title: 'Pending splitter debt + excess', + description: + 'pendingToSplit settles from bond on claim. Splitter debt row shows.', + data: { + bond: { current: 34, forKeys: 32, pendingToSplit: 0.3 }, + rewards: 0.5, + feeSplits: [50], + }, + expectOptions: [ALL, BOND, R2B], + }, + { + group: 'Splitters', + title: 'Splitters + insufficient + remainder', + description: + 'Split, compensate insufficient bond, send remainder to the Rewards Address.', + data: { bond: { current: 31, forKeys: 32 }, rewards: 2, feeSplits: [50] }, + expectOptions: [ALL, R2B], + }, + // [Misc] + { + group: 'Misc', + title: 'Paused accounting', + description: 'Accounting paused. Submit replaced by the paused button.', + data: { + bond: { current: 34, forKeys: 32 }, + rewards: 0.4, + isPaused: true, + }, + expectOptions: [ALL, BOND, R2B], + }, + { + group: 'Misc', + title: 'Rewards address is a contract', + description: + 'Rewards address is a contract. Default claim token is wstETH.', + data: { + bond: { current: 34, forKeys: 32 }, + rewards: 0.4, + isContract: true, + }, + expectOptions: [ALL, BOND, R2B], + }, + { + group: 'Misc', + title: 'Whale (large excess + rewards)', + description: 'Large amounts. ETH max is capped by MAX_ETH_AMOUNT.', + data: { bond: { current: 1000, forKeys: 900 }, rewards: 50 }, + expectOptions: [ALL, BOND, R2B], + }, + // [Repro] States reported from the live app — used to check option copy. + { + group: 'Repro', + title: 'Insufficient + splitters, rewards < deficit', + description: + 'forKeys-insufficient, splitters on, rewards do not cover the deficit (nothing splits, all compensates).', + data: { bond: { current: 31, forKeys: 32 }, rewards: 0.5, feeSplits: [40] }, + expectOptions: [R2B], + }, + { + group: 'Repro', + title: 'Locked hides excess + claimable rewards', + description: + 'Excess shown but fully locked (no claimable excess); rewards exceed the tiny locked deficit, so most rewards are claimable.', + data: { + bond: { current: 42.0999, forKeys: 32, locked: 10.1 }, + rewards: 0.2663, + }, + expectOptions: [ALL, R2B], + }, + { + group: 'Repro', + title: 'Sub-threshold deficit (nothing to compensate)', + description: + 'forKeys short by a few wei — SDK clamps to Excess Bond 0.0. No "compensate" copy or note should appear despite pending rewards.', + data: { + bond: { current: 32, forKeys: 32, deficitWei: 5 }, + rewards: 1.4779, + }, + expectOptions: [ALL, R2B], + }, +]; diff --git a/mock/queue/CLAUDE.md b/mock/queue/CLAUDE.md new file mode 100644 index 000000000..490e9107f --- /dev/null +++ b/mock/queue/CLAUDE.md @@ -0,0 +1,160 @@ +# Queue Mock Data Documentation + +This document describes the rules and relationships for creating realistic mock data for deposit queue testing scenarios. + +## Data Structure Overview + +The mock queue system simulates Lido's CSM (Community Staking Module) deposit queue with multiple priority levels and operator batches. + +## Core Data Relationships + +### 1. **depositableValidatorsCount vs Batch Data** + +`depositableValidatorsCount` represents the **actual** number of keys the operator can deposit, while batch data may contain **stale** information due to key removals. + +**Rules:** + +- `depositableValidatorsCount <= sum(operator's batches in all queues)` +- Batch data can be larger than `depositableValidatorsCount` (realistic - keys were removed but batches not updated) +- `depositableValidatorsCount` should never be larger than batch sum (impossible in real system) + +**Examples:** + +```javascript +// Realistic: Stale batch data (keys were removed) +operatorInfo: { depositableValidatorsCount: 15 } +operator batches total: 25 keys // ✅ Valid - 10 keys were removed + +// Realistic: Accurate batch data +operatorInfo: { depositableValidatorsCount: 30 } +operator batches total: 30 keys // ✅ Valid - data is current + +// Unrealistic: More depositable than batches +operatorInfo: { depositableValidatorsCount: 40 } +operator batches total: 25 keys // ❌ Invalid - impossible scenario +``` + +### 2. **shareLimit.queue vs Total Queue** + +`shareLimit.queue` represents the **actual** total of all queued keys across all operators. + +**Rules:** + +- `shareLimit.queue = sum(all keys in all priority queues)` +- `shareLimit.queue >= sum(all operators' depositableValidatorsCount)` +- Batch totals may differ from `shareLimit.queue` due to coefficient calculation + +### 3. **Priority System** + +**Realistic Priorities (Production Use):** + +- **Priority 0**: "Priority queue" - Highest priority, limited capacity per operator +- **Priority 5**: "General queue" - Default queue for most operators + +**Reserved Priorities (Future Use):** + +- **Priority 1-4**: Reserved for future features, minimal test coverage + +### 4. **CSM Capacity Limits** + +**Rules:** + +- `shareLimit.active + shareLimit.queue <= shareLimit.capacity` (under limit) +- `shareLimit.active + shareLimit.queue > shareLimit.capacity` (over limit scenario) +- `shareLimit.activeLeft = max(0, shareLimit.capacity - shareLimit.active)` + +### 5. **Key Submission Logic** + +When operator submits keys: + +- First fill their designated priority (0, 4, or 5) up to `maxDeposits` +- Overflow goes to Priority 5 (General queue) +- Never submit to priorities 1-3 in realistic scenarios + +## Test Scenario Guidelines + +### Realistic Scenarios Should: + +1. **Use priorities 0, 4, 5** primarily +2. **Respect stale batch data** - `depositableValidatorsCount <= batch sum` +3. **Match queue totals** - `shareLimit.queue = sum of all batch keys` +4. **Include edge cases** - zero capacity, single keys, operator at queue end +5. **Test batch merging** - adjacent operator batches should merge in visualization + +### Edge Cases to Include: + +1. **Stale Data Scenarios:** + + - Operator with 0 `depositableValidatorsCount` but has batches (all keys removed) + - Large batch sum vs small `depositableValidatorsCount` + +2. **Position Scenarios:** + + - Operator at beginning, middle, end of priority queues + - Operator as only batch in a priority + - Adjacent batches that should merge + +3. **Capacity Scenarios:** + + - Zero capacity + - Very low capacity (1-5 keys) + - Exactly at capacity limit + - Far over capacity limit + +4. **Multi-Priority Scenarios:** + + - Keys only in Priority 0 + - Keys only in Priority 5 + - Keys split between Priority 0 and 5 + - All priorities empty except Priority 5 + - All priorities (P0-P5) active with keys + - Operator distributed across all 6 priorities + - All priorities active but operator has no keys + +5. **All-Priority Scenarios:** + + - Comprehensive queue state with all 6 priorities populated + - Operator presence across every priority level (P0-P5) + - All priorities extending beyond capacity limits + - Full queue activity without current operator participation + +6. **Submission Scenarios:** + - Submitting to empty Priority 0 + - Priority 0 at limit, overflow to Priority 5 + - Large submission that spans multiple priorities + +## Data Validation Checklist + +Before adding a new test scenario, verify: + +- [ ] `depositableValidatorsCount <= sum(operator batches)` +- [ ] `shareLimit.queue = sum(all batch keys)` +- [ ] Uses realistic priorities (0, 4, 5) +- [ ] CSM limits are realistic +- [ ] Scenario has clear testing purpose +- [ ] Edge cases are properly documented + +## Common Pitfalls + +1. **Making `depositableValidatorsCount` larger than batch sum** - Impossible in real system +2. **Using priorities 1-3 in realistic scenarios** - These are reserved for future +3. **Ignoring stale batch data** - Real system often has outdated batch information +4. **Inconsistent queue totals** - `shareLimit.queue` must match actual queue sum +5. **Unrealistic capacity limits** - Should reflect real CSM constraints + +## Testing Groups + +Test scenarios are organized into logical groups (42 total scenarios): + +- **[Basic]** (5): Empty queue, active-only, within/over limits +- **[Priority]** (5): Distribution across production priorities (P0, P4, P5) +- **[Position]** (6): Operator placements - beginning, middle, end, single key scenarios +- **[Stale]** (3): Realistic batch data inconsistencies due to key removals +- **[Edge]** (3): Capacity limits - zero, extremely low, single keys +- **[Submit]** (3): Key submission patterns and priority allocation +- **[Fallback]** (3): Undefined data, error scenarios, general queue fallback +- **[Stress]** (2): Large-scale, high-volume testing +- **[Coeff]** (1): Queue coefficient calculation edge cases +- **[Reserved]** (4): Reserved priorities (P1-P3) for future feature testing +- **[All Priorities]** (4): Comprehensive testing with all 6 priorities active +- **[Real]** (3): Realistic edge cases - P5-only, far triggers, multi-priority operators diff --git a/mock/queue/mock-data.ts b/mock/queue/mock-data.ts new file mode 100644 index 000000000..c6c606d80 --- /dev/null +++ b/mock/queue/mock-data.ts @@ -0,0 +1,155 @@ +import { + ShareLimitInfo, + NodeOperatorInfo, + DepositQueueBatch, +} from '@lidofinance/lido-csm-sdk'; +import { DepositDataInputType } from 'shared/hook-form/deposit-data'; + +export type MockShareLimitParams = { + active: number; + queue: number; + capacity: number; + shareLimit?: number; +}; + +export type MockOperatorInfoParams = { + depositableValidatorsCount: number; + totalDepositedKeys?: number; + enqueuedCount?: number; +}; + +export type MockFormDataParams = { + depositDataLength: number; +}; + +export type MockDepositQueueParams = { + // Array of priority queues, each containing batches with [nodeOperatorId, keysCount] pairs + // Index 0 = Priority 0 (highest), Index 5 = Priority 5 (lowest) + priorities: Array>; +}; + +export type MockCurveParams = { + priority: number; + maxDeposits: number; + lowestPriority: number; +}; + +export type MockScenarioData = { + nodeOperatorId: number; + shareLimit: MockShareLimitParams; + operatorInfo: MockOperatorInfoParams; + formData: MockFormDataParams; + depositQueueBatches: MockDepositQueueParams | undefined; + curveParams?: MockCurveParams; +}; + +export const createMockShareLimit = ({ + active, + queue, + capacity, + shareLimit = capacity, +}: MockShareLimitParams): ShareLimitInfo => { + const activeBigInt = BigInt(active); + const queueBigInt = BigInt(queue); + const capacityBigInt = BigInt(capacity); + const shareLimitBigInt = BigInt(shareLimit); + + const activeLeft = + capacityBigInt > activeBigInt ? capacityBigInt - activeBigInt : 0n; + + return { + active: activeBigInt, + activeLeft, + capacity: capacityBigInt, + queue: queueBigInt, + shareLimit: shareLimitBigInt, + }; +}; + +export const createMockOperatorInfo = ({ + depositableValidatorsCount, + totalDepositedKeys = 0, + enqueuedCount = 0, +}: MockOperatorInfoParams): NodeOperatorInfo => { + return { + totalAddedKeys: 0, + totalWithdrawnKeys: 0, + totalDepositedKeys, + totalVettedKeys: 0, + stuckValidatorsCount: 0, + depositableValidatorsCount, + targetLimit: 0, + targetLimitMode: 0, + totalExitedKeys: 0, + enqueuedCount, + managerAddress: '0x0000000000000000000000000000000000000000', + rewardsAddress: '0x0000000000000000000000000000000000000000', + extendedManagerPermissions: false, + usedPriorityQueue: false, + }; +}; + +export const createMockDepositQueueBatches = ({ + priorities, +}: MockDepositQueueParams): DepositQueueBatch[][] => { + const mappedPriorities = priorities.map((priorityBatches) => + priorityBatches.map(([nodeOperatorId, keysCount]) => ({ + nodeOperatorId: BigInt(nodeOperatorId), + keysCount: keysCount, + })), + ); + + // Always return exactly 6 arrays (priorities 0-5) + const result: DepositQueueBatch[][] = []; + for (let i = 0; i < 6; i++) { + result.push(mappedPriorities[i] || []); + } + + return result; +}; + +export const createMockCurveParams = ({ + priority, + maxDeposits, + lowestPriority, +}: MockCurveParams) => { + return { + queueConfig: { + priority, + maxDeposits, + lowestPriority, + }, + }; +}; + +export const createMockFormData = ({ + depositDataLength, +}: MockFormDataParams): DepositDataInputType => { + const mockDepositItem = { + pubkey: + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + withdrawal_credentials: + '0x010000000000000000000000000000000000000000000000000000000000000000', + amount: 32000000000, + signature: + '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + deposit_message_root: + '0x0000000000000000000000000000000000000000000000000000000000000000', + deposit_data_root: + '0x0000000000000000000000000000000000000000000000000000000000000000', + fork_version: '0x00000000', + deposit_cli_version: '2.3.0', + network_name: 'mainnet', + } as const; + + const depositData = Array.from( + { length: depositDataLength }, + () => mockDepositItem, + ); + + return { + rawDepositData: undefined, + depositData, + confirmKeysReady: true, + }; +}; diff --git a/mock/queue/mock-providers.tsx b/mock/queue/mock-providers.tsx new file mode 100644 index 000000000..bb49f1a7b --- /dev/null +++ b/mock/queue/mock-providers.tsx @@ -0,0 +1,103 @@ +import { FC, PropsWithChildren } from 'react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { useForm, FormProvider } from 'react-hook-form'; +import { + createMockShareLimit, + createMockOperatorInfo, + createMockFormData, + createMockDepositQueueBatches, + createMockCurveParams, + type MockScenarioData, +} from './mock-data'; +import { + NodeOperatorContext, + NodeOperatorContextValue, +} from 'modules/web3/operator-provider/node-operator-provider'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import { + KEY_DEPOSIT_QUEUE_BATCHES, + KEY_OPERATOR_INFO, + KEY_SHARE_LIMIT, +} from 'modules/web3'; +import { hashKey } from 'utils'; + +// Main mock provider that combines all the mocking +export const MockDepositQueueProvider: FC< + PropsWithChildren<{ scenario: MockScenarioData }> +> = ({ children, scenario }) => { + const mockShareLimit = createMockShareLimit(scenario.shareLimit); + const mockOperatorInfo = createMockOperatorInfo(scenario.operatorInfo); + const mockFormData = createMockFormData(scenario.formData); + const mockDepositQueueBatches = scenario.depositQueueBatches + ? createMockDepositQueueBatches(scenario.depositQueueBatches) + : null; + const mockCurveParams = scenario.curveParams + ? createMockCurveParams(scenario.curveParams) + : undefined; + + // Create a unique QueryClient for this scenario to avoid cache conflicts + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + queryKeyHashFn: hashKey, + retry: false, + ...STRATEGY_IMMUTABLE, + }, + }, + }); + + // Pre-populate the query cache with mock data + queryClient.setQueryData(KEY_SHARE_LIMIT, mockShareLimit); + queryClient.setQueryData( + [...KEY_OPERATOR_INFO, { nodeOperatorId: BigInt(scenario.nodeOperatorId) }], + mockOperatorInfo, + ); + queryClient.setQueryData(KEY_DEPOSIT_QUEUE_BATCHES, mockDepositQueueBatches); + + // Mock curve parameters if provided + if (mockCurveParams) { + const mockCurveId = BigInt(0); // Default curve ID for testing + // Mock operator curve ID + queryClient.setQueryData( + [ + 'operator-curve-id', + { nodeOperatorId: BigInt(scenario.nodeOperatorId) }, + ], + mockCurveId, + ); + // Mock curve parameters + queryClient.setQueryData( + ['curve-parameters', { curveId: mockCurveId }], + mockCurveParams, + ); + } + + // Mock node operator context value + const mockNodeOperatorContextValue: NodeOperatorContextValue = { + isPending: false, + nodeOperator: { + id: BigInt(scenario.nodeOperatorId), + // Add other required properties if needed + } as any, + switchNodeOperator: () => {}, // Mock function + }; + + // Create form with mock data + const formMethods = useForm({ + defaultValues: mockFormData, + }); + + return ( + + + + {children} + + + + ); +}; + +// Note: These mock hooks are not exported as they conflict with the real hooks. +// Instead, the mock data is pre-populated in the QueryClient cache, +// so the real hooks will automatically use the mocked data. diff --git a/mock/queue/real-case-scenario.ts b/mock/queue/real-case-scenario.ts new file mode 100644 index 000000000..6acc37a09 --- /dev/null +++ b/mock/queue/real-case-scenario.ts @@ -0,0 +1,171 @@ +import { TestScenario } from './test-scenarios'; + +/** + * Real production queue data snapshot + * + * This scenario is based on actual production queue state captured from mainnet. + * It represents a real-world distribution of validators across priorities with + * operator 346 being the primary focus (having the most keys in priority 4). + * + * Key characteristics: + * - High-volume scenario with 8869 active validators + * - Large capacity (13257) with 2331 in queue + * - Priorities 0-3 are empty + * - Priority 4 contains the bulk of queued keys + * - Priority 5 has additional diverse operator distribution + * - Note: Original data had priority 6, excluded for system compatibility (expects 6 priorities: 0-5) + */ +export const realCaseScenario: TestScenario = { + title: '[Real] Production Queue Snapshot', + description: + 'Real mainnet queue state - operator 346 dominates priority 4 with 905 keys, high-volume scenario with 8869 active validators', + data: { + nodeOperatorId: 253, + shareLimit: { + active: 8869, + queue: 2331, + capacity: 13257, + shareLimit: 500, + }, + operatorInfo: { + depositableValidatorsCount: 1, // Matches operator 346's total keys in priority 4 + }, + formData: { + depositDataLength: 0, // No new keys being submitted + }, + depositQueueBatches: { + priorities: [ + // Priority 0: Empty (highest priority) + [], + // Priority 1: Empty (reserved) + [], + // Priority 2: Empty (reserved) + [], + // Priority 3: Empty (reserved) + [], + // Priority 4: Legacy queue - operator 346 dominates with 905 keys + [ + [346, 51], + [346, 150], + [346, 150], + [346, 150], + [346, 150], + [346, 150], + [346, 103], + [346, 1], + [457, 1], + [457, 25], + [239, 1], + [458, 25], + [458, 25], + [458, 25], + [458, 15], + [457, 25], + [457, 25], + [457, 25], + [452, 1], + [457, 25], + [457, 25], + [457, 25], + [457, 25], + [459, 1], + [99, 2], + [460, 3], + [461, 1], + [333, 25], + [344, 5], + [344, 4], + [333, 25], + [333, 25], + [333, 25], + [427, 1], + [325, 2], + [125, 25], + [125, 25], + [125, 18], + [427, 1], + [99, 1], + [463, 1], + [357, 1], + [295, 3], + ], + // Priority 5: General queue - diverse operator distribution + [ + [253, 1], + [464, 15], + [465, 1], + [25, 3], + [25, 1], + [49, 4], + [206, 1], + [286, 2], + [291, 15], + [466, 100], + [103, 1], + [237, 10], + [427, 1], + [257, 2], + [427, 1], + [207, 4], + [127, 15], + [466, 20], + [201, 5], + [185, 4], + [243, 4], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [399, 10], + [469, 6], + [464, 14], + [294, 64], + [460, 3], + [294, 77], + [171, 100], + [50, 5], + [17, 1], + [17, 1], + [17, 1], + [17, 1], + [17, 1], + [17, 1], + [470, 1], + [471, 1], + [260, 6], + [464, 61], + [472, 1], + [461, 2], + [152, 80], + [473, 1], + [99, 1], + ], + ], + }, + }, +}; diff --git a/mock/queue/test-scenarios.ts b/mock/queue/test-scenarios.ts new file mode 100644 index 000000000..48ef227a9 --- /dev/null +++ b/mock/queue/test-scenarios.ts @@ -0,0 +1,1848 @@ +import { MockScenarioData } from './mock-data'; +import { realCaseScenario } from './real-case-scenario'; + +export type TestScenario = { + title: string; + description: string; + data: MockScenarioData; +}; + +export const testScenarios: TestScenario[] = [ + // ======================================== + // GROUP 0: REAL PRODUCTION DATA + // ======================================== + realCaseScenario, + { + title: '[Real] Large Active with Tiny Priority Queue', + description: + 'High active count (17581) with minimal priority queue (10) and large general queue (3444), limit just above total', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 17581, + queue: 3454, // 10 + 3444 + capacity: 22169, + }, + operatorInfo: { + depositableValidatorsCount: 0, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [[2, 10]], // Priority 0: 10 keys + [], + [], + [], // Reserved + [], // Priority 4: Empty + [ + [3, 1500], + [4, 1000], + [5, 944], + ], // Priority 5: 3444 keys total + ], + }, + }, + }, + { + title: '[Real] All Priorities Empty Except P5', + description: 'Realistic scenario where only general queue has validators', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 150, + queue: 180, + capacity: 500, + }, + operatorInfo: { + depositableValidatorsCount: 50, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [], + [], + [], + [], // Priorities 0-4: Empty + [ + [1, 50], + [2, 70], + [3, 60], + ], // Priority 5: All keys here + ], + }, + }, + }, + { + title: '[Real] Far Away Indicator Trigger', + description: 'Small queue with large capacity triggering far-away view', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 50, + queue: 25, + capacity: 2000, // Very large capacity + }, + operatorInfo: { + depositableValidatorsCount: 8, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [[2, 10]], // Priority 0: Small queue + [], + [], + [], + [], // Empty priorities + [ + [1, 8], + [3, 7], + ], // Priority 5: Small operator presence + ], + }, + }, + }, + { + title: '[Real] Operator Across All Production Priorities', + description: 'Operator has keys in P0, P4, and P5 simultaneously', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 400, + queue: 350, + capacity: 900, + }, + operatorInfo: { + depositableValidatorsCount: 140, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 60], + [2, 50], + ], // Priority 0: Operator present + [], + [], + [], // Reserved + [ + [1, 40], + [3, 70], + ], // Priority 4: Operator present + [ + [1, 40], + [4, 60], + [5, 30], + ], // Priority 5: Operator present + ], + }, + }, + }, + + // ======================================== + // GROUP A: BASIC QUEUE STATES + // ======================================== + { + title: '[Basic] Empty Queue', + description: 'No active keys, no queued keys - fresh start state', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 0, + queue: 0, + capacity: 1000, + }, + operatorInfo: { + depositableValidatorsCount: 0, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [[], [], [], [], [], []], // All priorities empty + }, + }, + }, + { + title: '[Basic] Active Keys Only - No Queue', + description: + 'Only active validators, empty queue - typical established operator', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 250, + queue: 0, + capacity: 1000, + }, + operatorInfo: { + depositableValidatorsCount: 0, // No keys in queue + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [[], [], [], [], [], []], // All priorities empty + }, + }, + }, + { + title: '[Basic] Queue Within CSM Limit', + description: 'Active + queue stays within CSM capacity', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 150, + capacity: 1000, + }, + operatorInfo: { + depositableValidatorsCount: 65, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [[1, 45]], // Priority 0: 45 keys for operator 1 + [], + [], + [], // Priorities 1-3: Empty (reserved) + [[2, 40]], // Priority 4: Other operator + [ + [1, 20], + [3, 45], + ], // Priority 5: 20 keys for operator 1, others + ], + }, + }, + }, + { + title: '[Basic] Queue Exactly at CSM Limit', + description: 'Queue fills exactly to CSM capacity', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 400, + queue: 100, + capacity: 500, + }, + operatorInfo: { + depositableValidatorsCount: 45, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 35], + [1, 30], + ], // Priority 0: operator at end + [], + [], + [], // Reserved priorities + [], // Priority 4: empty + [ + [1, 15], + [3, 20], + ], // Priority 5: operator first, others + ], + }, + }, + }, + { + title: '[Basic] Queue Exceeds CSM Limit', + description: 'Queue extends beyond CSM capacity - over limit scenario', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 250, + capacity: 450, // Only 150 capacity left + }, + operatorInfo: { + depositableValidatorsCount: 90, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 60], + [1, 50], + ], // Priority 0: 110 total + [], + [], + [], // Reserved + [[3, 40]], // Priority 4: 40 keys + [ + [1, 40], + [4, 60], + ], // Priority 5: 100 total + ], + }, + }, + }, + + // ======================================== + // GROUP B: PRIORITY DISTRIBUTION (0, 4, 5) + // ======================================== + { + title: '[Priority] Keys Only in Priority 0', + description: 'All validators in highest priority queue only', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 200, + queue: 180, + capacity: 600, + }, + operatorInfo: { + depositableValidatorsCount: 80, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 80], + [2, 60], + [3, 40], + ], // Priority 0: All keys here + [], + [], + [], + [], + [], // All other priorities empty + ], + }, + }, + }, + { + title: '[Priority] Keys Only in Legacy Queue (P4)', + description: 'All validators in legacy priority queue only', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 150, + queue: 200, + capacity: 500, + }, + operatorInfo: { + depositableValidatorsCount: 55, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [], + [], + [], + [], // Priorities 0-3: Empty + [ + [2, 70], + [1, 55], + [3, 45], + [4, 30], + ], // Priority 4: All keys here + [], // Priority 5: Empty + ], + }, + }, + }, + { + title: '[Priority] Keys Only in General Queue (P5)', + description: 'All validators in general (lowest) priority queue only', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 100, + queue: 250, + capacity: 600, + }, + operatorInfo: { + depositableValidatorsCount: 75, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [], + [], + [], + [], + [], // Priorities 0-4: Empty + [ + [2, 80], + [1, 75], + [3, 60], + [4, 35], + ], // Priority 5: All keys here + ], + }, + }, + }, + { + title: '[Priority] Keys in Priority 0 and 5 Only', + description: 'Edge priorities only - highest and lowest priority', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 200, + queue: 220, + capacity: 600, + }, + operatorInfo: { + depositableValidatorsCount: 90, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 50], + [1, 60], + ], // Priority 0: 110 total + [], + [], + [], // Priorities 1-3: Reserved + [], // Priority 4: Empty + [ + [1, 30], + [3, 80], + ], // Priority 5: 110 total + ], + }, + }, + }, + { + title: '[Priority] Keys in Priority 0, 4, and 5', + description: 'Realistic distribution across production priorities', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 250, + queue: 300, + capacity: 700, + }, + operatorInfo: { + depositableValidatorsCount: 105, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 50], + [2, 40], + ], // Priority 0: 90 total + [], + [], + [], // Reserved priorities + [ + [3, 60], + [1, 35], + ], // Priority 4: 95 total + [ + [1, 20], + [4, 55], + [5, 40], + ], // Priority 5: 115 total + ], + }, + }, + }, + + // ======================================== + // GROUP C: OPERATOR POSITION SCENARIOS + // ======================================== + { + title: '[Position] Operator at Beginning of Queues', + description: 'Operator batches positioned at start of priority segments', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 320, // 120 + 120 + 80 = 320 total + capacity: 800, + }, + operatorInfo: { + depositableValidatorsCount: 80, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 50], + [2, 40], + [3, 30], + ], // Priority 0: Operator first + [], + [], + [], // Reserved + [ + [1, 30], + [4, 50], + [5, 40], + ], // Priority 4: Operator first + [ + [6, 30], + [7, 20], + [8, 30], + ], // Priority 5: No operator + ], + }, + }, + }, + { + title: '[Position] Operator at End of Queues', + description: 'Operator batches positioned at end of priority segments', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 250, + queue: 260, + capacity: 700, + }, + operatorInfo: { + depositableValidatorsCount: 75, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 60], + [3, 40], + [1, 45], + ], // Priority 0: Operator last + [], + [], + [], // Reserved + [], // Priority 4: Empty + [ + [4, 50], + [5, 35], + [1, 30], + ], // Priority 5: Operator last + ], + }, + }, + }, + { + title: '[Position] Operator with Adjacent Batches (Should Merge)', + description: + 'Consecutive operator batches that should merge in visualization', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 285, // 130 + 85 + 70 = 285 total + capacity: 800, + }, + operatorInfo: { + depositableValidatorsCount: 85, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 30], + [1, 25], + [1, 35], + [3, 40], + ], // Priority 0: Adjacent operator batches pos 2-3 + [], + [], + [], // Reserved + [ + [1, 20], + [1, 5], + [4, 60], + ], // Priority 4: Adjacent operator batches pos 1-2 + [ + [5, 40], + [6, 30], + ], // Priority 5: No operator + ], + }, + }, + }, + { + title: '[Position] Operator as Only Batch in Priority', + description: 'Priority segments where operator is the sole participant', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 200, + queue: 140, + capacity: 500, + }, + operatorInfo: { + depositableValidatorsCount: 90, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [[1, 60]], // Priority 0: Only operator + [], + [], + [], // Reserved + [[1, 30]], // Priority 4: Only operator + [ + [2, 40], + [3, 10], + ], // Priority 5: Other operators only + ], + }, + }, + }, + { + title: '[Position] Operator Single Key at Very End of Queue', + description: + 'Operator has exactly 1 key positioned at the absolute end of all queues', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 200, + queue: 291, // 140 + 90 + 61 = 291 total + capacity: 500, + }, + operatorInfo: { + depositableValidatorsCount: 1, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 80], + [3, 60], + ], // Priority 0: Other operators + [], + [], + [], // Reserved priorities + [ + [4, 50], + [5, 40], + ], // Priority 4: Other operators + [ + [6, 30], + [7, 20], + [8, 10], + [1, 1], + ], // Priority 5: Operator at very end + ], + }, + }, + }, + { + title: '[Position] Single Key at End + Submitting One More', + description: 'Operator has 1 key at queue end and submits 1 additional key', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 150, + queue: 241, // 120 + 60 + 61 = 241 total + capacity: 400, + }, + operatorInfo: { + depositableValidatorsCount: 1, // Current queue keys + totalDepositedKeys: 20, + enqueuedCount: 1, + }, + formData: { + depositDataLength: 1, // Submitting 1 more key + }, + curveParams: { + priority: 0, + maxDeposits: 30, // Room for 9 more (30 - 20 deposited - 1 queued) + lowestPriority: 5, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 70], + [3, 50], + ], // Priority 0: Other operators, will receive the new key + [], + [], + [], // Reserved priorities + [[4, 60]], // Priority 4: Other operator + [ + [5, 40], + [6, 20], + [1, 1], + ], // Priority 5: Operator at very end with 1 key + ], + }, + }, + }, + + // ======================================== + // GROUP D: STALE BATCH DATA EDGE CASES + // ======================================== + { + title: '[Stale] Operator with Zero Depositable Keys', + description: + 'All operator keys removed but batches still in queue (stale data)', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 400, + queue: 200, + capacity: 800, + }, + operatorInfo: { + depositableValidatorsCount: 0, // All keys were removed, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 40], + [2, 50], + ], // Priority 0: Stale operator batch + [], + [], + [], // Reserved + [], // Priority 4: Empty + [ + [1, 35], + [3, 75], + ], // Priority 5: More stale operator batches + ], + }, + }, + }, + { + title: '[Stale] Large Batch Sum vs Small Depositable Count', + description: 'Significant difference due to key removals', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 350, + queue: 250, + capacity: 800, + }, + operatorInfo: { + depositableValidatorsCount: 15, // Very small compared to batch sum (120) + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 80], + [2, 60], + ], // Priority 0: Large stale batch + [], + [], + [], // Reserved + [ + [1, 40], + [3, 70], + ], // Priority 4: More stale batches + [], // Priority 5: Empty + ], + }, + }, + }, + { + title: '[Stale] Multiple Operators with Stale Data', + description: + 'Several operators have inconsistent batch vs depositable counts', + data: { + nodeOperatorId: 2, // Focus on operator 2 + shareLimit: { + active: 300, + queue: 400, + capacity: 900, + }, + operatorInfo: { + depositableValidatorsCount: 25, // Much less than batch sum (80) + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 100], + [2, 50], + ], // Priority 0: Op 1 has 100, Op 2 has 50 (stale) + [], + [], + [], // Reserved + [ + [2, 30], + [3, 90], + ], // Priority 4: More stale data for Op 2 + [ + [4, 60], + [5, 70], + ], // Priority 5: Other operators + ], + }, + }, + }, + + // ======================================== + // GROUP E: CAPACITY & LIMIT EDGE CASES + // ======================================== + { + title: '[Edge] Zero Capacity', + description: 'Testing edge case with zero CSM capacity', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 100, + queue: 50, + capacity: 0, // Edge case + }, + operatorInfo: { + depositableValidatorsCount: 30, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [[1, 30]], // Priority 0: Over limit + [], + [], + [], + [], // Other priorities + [[2, 20]], // Priority 5: Other operator + ], + }, + }, + }, + { + title: '[Edge] Extremely Low Capacity (2 keys room)', + description: 'Very tight capacity limit with large queue', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 198, + queue: 150, + capacity: 200, // Only 2 keys room left + }, + operatorInfo: { + depositableValidatorsCount: 45, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [[2, 50]], // Priority 0: Other operator, over limit + [], + [], + [], // Reserved + [], // Priority 4: Empty + [ + [1, 45], + [3, 55], + ], // Priority 5: All over limit + ], + }, + }, + }, + { + title: '[Edge] Single Key Scenarios', + description: 'Minimum width testing with single validator keys', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 100, + queue: 6, + capacity: 200, + }, + operatorInfo: { + depositableValidatorsCount: 4, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [[1, 2]], // Priority 0: 2 keys + [], + [], + [], // Reserved + [[1, 1]], // Priority 4: 1 key + [ + [1, 1], + [2, 2], + ], // Priority 5: Mixed + ], + }, + }, + }, + + // ======================================== + // GROUP F: KEY SUBMISSION SCENARIOS + // ======================================== + { + title: '[Submit] Submitting to Empty Priority 0', + description: 'Priority 0 empty, all 20 submitted keys should go to P0', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 100, + capacity: 600, + }, + operatorInfo: { + depositableValidatorsCount: 0, // No current queue keys + totalDepositedKeys: 10, + enqueuedCount: 0, + }, + formData: { + depositDataLength: 20, // Submitting 20 keys + }, + curveParams: { + priority: 0, + maxDeposits: 50, // Room for 40 more (50 - 10 deposited) + lowestPriority: 5, + }, + depositQueueBatches: { + priorities: [ + [], // Priority 0: Empty, will receive all 20 keys + [], + [], + [], // Reserved + [[2, 40]], // Priority 4: Other operator + [[3, 60]], // Priority 5: Other operator + ], + }, + }, + }, + { + title: '[Submit] Priority 0 Partial, Split Submission', + description: 'P0 partially full, keys split between P0 and P5', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 250, + queue: 150, + capacity: 600, + }, + operatorInfo: { + depositableValidatorsCount: 0, + totalDepositedKeys: 25, + enqueuedCount: 10, + }, + formData: { + depositDataLength: 18, // Submitting 18 keys + }, + curveParams: { + priority: 0, + maxDeposits: 40, // Only 5 slots left (40 - 25 deposited - 10 queued) + lowestPriority: 5, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 60], + [3, 40], + ], // Priority 0: Has other operators + [], + [], + [], // Reserved + [], // Priority 4: Empty + [[4, 50]], // Priority 5: Will receive overflow (13 keys) + ], + }, + }, + }, + { + title: '[Submit] Priority 0 at Max, All to P5', + description: 'P0 at maxDeposits limit, all submitted keys go to P5', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 200, + capacity: 700, + }, + operatorInfo: { + depositableValidatorsCount: 0, + totalDepositedKeys: 30, + enqueuedCount: 20, + }, + formData: { + depositDataLength: 15, // Submitting 15 keys + }, + curveParams: { + priority: 0, + maxDeposits: 50, // Already at limit (30 deposited + 20 queued) + lowestPriority: 5, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 80], + [3, 60], + ], // Priority 0: At capacity + [], + [], + [], // Reserved + [], // Priority 4: Empty + [[4, 60]], // Priority 5: Will receive all 15 keys + ], + }, + }, + }, + + { + title: '[Submit] Empty Priority Queue with Keys in General Queue', + description: + 'Active keys present, P0 empty, submitting 10 keys, general queue with 50 keys and operator batch of 5 at end', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 250, + queue: 50, // 25 + 20 + 5 = 50 total + capacity: 500, + }, + operatorInfo: { + depositableValidatorsCount: 5, // Current queue keys + totalDepositedKeys: 50, + enqueuedCount: 5, + }, + formData: { + depositDataLength: 10, // Submitting 10 keys + }, + curveParams: { + priority: 0, + maxDeposits: 70, // Room for 15 more (70 - 50 deposited - 5 queued) + lowestPriority: 5, + }, + depositQueueBatches: { + priorities: [ + [], // Priority 0: Empty, will receive all 10 submitted keys + [], + [], + [], // Reserved priorities + [], // Priority 4: Empty + [ + [2, 25], + [3, 20], + [1, 5], + ], // Priority 5: General queue, 50 total with operator at end + ], + }, + }, + }, + + // ======================================== + // GROUP G: FALLBACK SCENARIOS + // ======================================== + { + title: '[Fallback] Undefined Queue Data (Fallback Mode)', + description: 'Queue analysis failed, triggers general queue display', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 250, + queue: 180, + capacity: 600, + }, + operatorInfo: { + depositableValidatorsCount: 45, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: undefined, // Triggers fallback + }, + }, + { + title: '[Fallback] Fallback with Queue Over Limit', + description: 'Fallback mode with queue exceeding CSM capacity', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 400, + queue: 350, // Over limit + capacity: 600, + }, + operatorInfo: { + depositableValidatorsCount: 85, + }, + formData: { + depositDataLength: 12, + }, + depositQueueBatches: undefined, // Triggers fallback + }, + }, + { + title: '[Fallback] Fallback with Keys Being Added', + description: 'Fallback mode while operator is submitting new keys', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 200, + capacity: 700, + }, + operatorInfo: { + depositableValidatorsCount: 65, + }, + formData: { + depositDataLength: 25, // Large key submission + }, + depositQueueBatches: undefined, // Triggers fallback + }, + }, + + // ======================================== + // GROUP H: LARGE SCALE & STRESS TESTS + // ======================================== + { + title: '[Stress] High Volume Scenario', + description: 'Large-scale testing with thousands of keys', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 8000, + queue: 4200, // 1900 + 1000 + 1300 = 4200 total + capacity: 15000, + }, + operatorInfo: { + depositableValidatorsCount: 1200, + }, + formData: { + depositDataLength: 100, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 600], + [2, 800], + [3, 500], + ], // Priority 0: 1900 total + [], + [], + [], // Reserved + [ + [1, 400], + [4, 600], + ], // Priority 4: 1000 total + [ + [1, 200], + [5, 700], + [6, 400], + ], // Priority 5: 1300 total + ], + }, + }, + }, + { + title: '[Stress] Maximum Queue Stress Test', + description: 'Extreme scenario testing system limits', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 5000, + queue: 10000, + capacity: 12000, + }, + operatorInfo: { + depositableValidatorsCount: 3000, + }, + formData: { + depositDataLength: 200, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 1000], + [2, 1500], + [3, 1000], + ], // Priority 0: 3500 total + [], + [], + [], // Reserved + [ + [1, 1200], + [4, 800], + [5, 1000], + ], // Priority 4: 3000 total + [ + [1, 800], + [6, 1200], + [7, 1500], + ], // Priority 5: 3500 total + ], + }, + }, + }, + + // ======================================== + // GROUP I: QUEUE COEFFICIENT SCENARIOS + // ======================================== + { + title: '[Coeff] Queue Sum Mismatch (Coefficient Test)', + description: + 'Batch totals differ from shareLimit.queue for coefficient calculation', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 250, // Doesn't match actual batch sum (300) + capacity: 800, + }, + operatorInfo: { + depositableValidatorsCount: 60, // Less than batch sum (80) + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 50], + [2, 60], + ], // Priority 0: 110 total + [], + [], + [], // Reserved + [ + [1, 30], + [3, 70], + ], // Priority 4: 100 total + [[4, 90]], // Priority 5: 90 total + // Total: 300 (doesn't match shareLimit.queue: 250) + ], + }, + }, + }, + + // ======================================== + // GROUP J: RESERVED PRIORITIES SCENARIOS + // ======================================== + { + title: '[Reserved] Keys Only in Reserved Priority 1', + description: + 'Testing reserved priority P1 - minimal usage for future feature testing', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 200, + queue: 150, + capacity: 500, + }, + operatorInfo: { + depositableValidatorsCount: 50, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [], // Priority 0: Empty + [ + [1, 50], + [2, 60], + [3, 40], + ], // Priority 1: Reserved - testing usage + [], + [], + [], + [], // Other priorities empty + ], + }, + }, + }, + { + title: '[Reserved] Keys Across Reserved Priorities P1-P3', + description: + 'Testing all reserved priorities P1, P2, P3 for future feature compatibility', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 280, + capacity: 700, + }, + operatorInfo: { + depositableValidatorsCount: 90, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [], // Priority 0: Empty + [ + [1, 40], + [2, 30], + ], // Priority 1: Reserved + [ + [1, 30], + [3, 50], + ], // Priority 2: Reserved + [ + [1, 20], + [4, 40], + ], // Priority 3: Reserved + [], // Priority 4: Empty + [[5, 70]], // Priority 5: Other operator + ], + }, + }, + }, + { + title: '[Reserved] Mixed Production and Reserved Priorities', + description: + 'Operator has keys in both production (P0, P5) and reserved (P2) priorities', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 250, + queue: 320, + capacity: 800, + }, + operatorInfo: { + depositableValidatorsCount: 100, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 50], + [2, 40], + ], // Priority 0: Production priority + [], // Priority 1: Empty + [ + [1, 30], + [3, 60], + ], // Priority 2: Reserved priority with operator + [], // Priority 3: Empty + [[4, 70]], // Priority 4: Other operator + [ + [1, 20], + [5, 50], + ], // Priority 5: Production priority + ], + }, + }, + }, + { + title: '[Reserved] Reserved Priority Over Capacity Limit', + description: 'Reserved priority P2 extends beyond CSM capacity limit', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 450, + queue: 200, + capacity: 500, // Only 50 capacity left + }, + operatorInfo: { + depositableValidatorsCount: 80, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [[2, 30]], // Priority 0: Under limit (30 keys) + [], // Priority 1: Empty + [ + [1, 80], + [3, 90], + ], // Priority 2: Reserved, crosses and exceeds limit + [], + [], + [], // Other priorities empty + ], + }, + }, + }, + + // ======================================== + // GROUP K: ALL PRIORITIES SCENARIOS + // ======================================== + { + title: '[All Priorities] Comprehensive Queue with All 6 Priorities', + description: 'All priorities (P0-P5) have keys - comprehensive queue state', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 300, + queue: 580, // 100 + 80 + 90 + 70 + 110 + 130 = 580 total + capacity: 1200, + }, + operatorInfo: { + depositableValidatorsCount: 105, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 60], + [1, 40], + ], // Priority 0: 100 total + [ + [3, 50], + [4, 30], + ], // Priority 1: 80 total + [ + [1, 35], + [5, 55], + ], // Priority 2: 90 total + [ + [6, 45], + [7, 25], + ], // Priority 3: 70 total + [ + [1, 30], + [8, 80], + ], // Priority 4: 110 total + [ + [9, 70], + [10, 40], + [11, 20], + ], // Priority 5: 130 total + ], + }, + }, + }, + { + title: '[All Priorities] Operator Distributed Across All 6 Priorities', + description: 'Operator has keys in every priority queue (P0-P5)', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 250, + queue: 420, // 90 + 60 + 80 + 50 + 70 + 70 = 420 total + capacity: 800, + }, + operatorInfo: { + depositableValidatorsCount: 125, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 30], + [2, 60], + ], // Priority 0: Operator first, 90 total + [ + [3, 40], + [1, 20], + ], // Priority 1: Operator second, 60 total + [ + [1, 25], + [4, 55], + ], // Priority 2: Operator first, 80 total + [ + [5, 35], + [1, 15], + ], // Priority 3: Operator last, 50 total + [ + [1, 20], + [6, 50], + ], // Priority 4: Operator first, 70 total + [ + [7, 35], + [1, 15], + [8, 20], + ], // Priority 5: Operator middle, 70 total + ], + }, + }, + }, + { + title: '[All Priorities] All Priorities Over Capacity Limit', + description: + 'Every priority extends beyond CSM capacity - extreme over-limit', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 480, + queue: 650, // 120 + 100 + 110 + 90 + 120 + 110 = 650 total + capacity: 500, // Only 20 capacity left - all priorities over limit + }, + operatorInfo: { + depositableValidatorsCount: 95, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 70], + [1, 50], + ], // Priority 0: 120 total (over limit) + [ + [3, 60], + [4, 40], + ], // Priority 1: 100 total (over limit) + [ + [1, 25], + [5, 85], + ], // Priority 2: 110 total (over limit) + [ + [6, 50], + [7, 40], + ], // Priority 3: 90 total (over limit) + [ + [1, 20], + [8, 100], + ], // Priority 4: 120 total (over limit) + [ + [9, 70], + [10, 40], + ], // Priority 5: 110 total (over limit) + ], + }, + }, + }, + { + title: '[All Priorities] All Priorities Active - No Current Operator', + description: + 'All priorities (P0-P5) have keys but current operator has none', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 200, + queue: 480, // 80 + 70 + 90 + 60 + 100 + 80 = 480 total + capacity: 1000, + }, + operatorInfo: { + depositableValidatorsCount: 0, // No keys in queue + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 50], + [3, 30], + ], // Priority 0: 80 total, no operator 1 + [ + [4, 40], + [5, 30], + ], // Priority 1: 70 total, no operator 1 + [ + [6, 55], + [7, 35], + ], // Priority 2: 90 total, no operator 1 + [ + [8, 35], + [9, 25], + ], // Priority 3: 60 total, no operator 1 + [ + [10, 60], + [11, 40], + ], // Priority 4: 100 total, no operator 1 + [ + [12, 50], + [13, 30], + ], // Priority 5: 80 total, no operator 1 + ], + }, + }, + }, + { + title: '[All Priorities] All Priorities Active - Little Submitted Keys', + description: + 'All priorities (P0-P5) have keys with current operator having few keys at the end', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 200, + queue: 483, // 80 + 70 + 90 + 60 + 100 + 83 = 483 total (3 extra keys from operator 1) + capacity: 1000, + }, + operatorInfo: { + depositableValidatorsCount: 3, // Small number of keys + }, + formData: { + depositDataLength: 3, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 50], + [3, 30], + ], // Priority 0: 80 total, no operator 1 + [ + [4, 40], + [5, 30], + ], // Priority 1: 70 total, no operator 1 + [ + [6, 55], + [7, 35], + ], // Priority 2: 90 total, no operator 1 + [ + [8, 35], + [9, 25], + ], // Priority 3: 60 total, no operator 1 + [ + [10, 60], + [11, 40], + ], // Priority 4: 100 total, no operator 1 + [ + [12, 50], + [13, 30], + [1, 3], + ], // Priority 5: 83 total, operator 1 at the end with 3 keys + ], + }, + }, + }, + + // ======================================== + // GROUP L: METADATA MERGING & COMBINING + // ======================================== + { + title: '[Merge] Consecutive Batches Same Priority', + description: + 'Two consecutive operator batches in same priority should merge metadata', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 200, + queue: 60, + capacity: 500, + }, + operatorInfo: { + depositableValidatorsCount: 60, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 25], + [1, 35], + ], // Priority 0: Consecutive operator batches (positions 0-25, 25-60) + [], + [], + [], + [], + [], + ], + }, + }, + }, + { + title: '[Merge] Non-Consecutive Batches Same Priority', + description: + 'Operator batches with gap between them should NOT merge metadata', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 150, + queue: 70, + capacity: 400, + }, + operatorInfo: { + depositableValidatorsCount: 60, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [1, 25], + [2, 10], + [1, 35], + ], // Priority 0: Operator batches with gap (positions 0-25, 35-60) + [], + [], + [], + [], + [], + ], + }, + }, + }, + { + title: '[Merge] Consecutive Batches Different Priorities', + description: + 'Consecutive operator batches across different priorities should NOT merge', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 250, + queue: 60, + capacity: 500, + }, + operatorInfo: { + depositableValidatorsCount: 60, + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [[1, 30]], // Priority 0: Operator batch + [], + [], + [], + [[1, 30]], // Priority 4: Operator batch (different priority array) + [], + ], + }, + }, + }, + { + title: '[Combine] Four Metadata Items', + description: + 'Four metadata items in clustered batches should combine with combined flag (> MAX_TOOLTIP_ITEMS)', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 500, + queue: 2000, // Large queue for 0.5% = 10 keys tolerance + capacity: 3000, + }, + operatorInfo: { + depositableValidatorsCount: 90, // 20 + 25 + 15 + 30 = 90 + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 500], + [1, 20], + [3, 3], + [1, 25], + [4, 400], + [1, 15], + [5, 3], + [1, 30], + [6, 4], + ], // Priority 0: Operator batches clustered in 2 groups (500-548, 948-996) + [], + [], + [], + [], + [[7, 1000]], // Priority 5: Large other operator batch + ], + }, + }, + }, + { + title: '[Combine] Five Plus Metadata Items', + description: + 'Five metadata items in multiple clusters should combine with combined flag', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 800, + queue: 3000, // Large queue for 0.5% = 15 keys tolerance + capacity: 4500, + }, + operatorInfo: { + depositableValidatorsCount: 130, // 25 + 30 + 20 + 30 + 25 = 130 + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 800], + [1, 25], + [3, 5], + [1, 30], + [4, 5], + [1, 20], + [5, 115], + ], // Priority 0: 3 operator batches clustered at 800-885 (gaps of 5 keys) + [], + [], + [], + [ + [6, 400], + [1, 30], + [7, 5], + [1, 25], + [8, 140], + ], // Priority 4: 2 operator batches clustered at 400-460 (gap of 5 keys) + [[9, 1400]], // Priority 5: Large other operator batch + ], + }, + }, + }, + { + title: '[Combine] Exactly Three Metadata Items', + description: + 'Boundary case: Exactly 3 metadata items in one cluster should NOT combine (≤ MAX_TOOLTIP_ITEMS)', + data: { + nodeOperatorId: 1, + shareLimit: { + active: 500, + queue: 2000, // Large queue for 0.5% = 10 keys tolerance + capacity: 3000, + }, + operatorInfo: { + depositableValidatorsCount: 75, // 30 + 25 + 20 = 75 + }, + formData: { + depositDataLength: 0, + }, + depositQueueBatches: { + priorities: [ + [ + [2, 800], + [1, 30], + [3, 5], + [1, 25], + [4, 5], + [1, 20], + [5, 115], + ], // Priority 0: 3 operator batches clustered at 800-885 (gaps of 5 keys) + [], + [], + [], + [], + [[6, 1000]], // Priority 5: Large other operator batch + ], + }, + }, + }, +]; diff --git a/mock/rewards/data.ts b/mock/rewards/data.ts new file mode 100644 index 000000000..5d16f4c7d --- /dev/null +++ b/mock/rewards/data.ts @@ -0,0 +1,69662 @@ +export const data = [ + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.0012698412698412698, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.0012698412698412698, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.0006349206349206349, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.0006349206349206349, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.0012698412698412698, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.0006349206349206349, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.0006349206349206349, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.0019047619047619048, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.0006349206349206349, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.0012698412698412698, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.0012698412698412698, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.0006349206349206349, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.0006349206349206349, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.0005911330049261084, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.001773399014778325, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.0006349206349206349, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1712871n, + refSlot: 1842399n, + frame: [56000, 57574], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0, + threshold: 0.9070561498332749, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1763717400, + endTimestamp: 1764321816, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.8457142857142858, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.8457142857142858, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.8476190476190476, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.8457142857142858, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.8457142857142858, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.8457142857142858, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.8476190476190476, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.8476190476190476, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.8476190476190476, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.8450793650793651, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.8476190476190476, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.8482539682539683, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.8450793650793651, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.8476190476190476, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.8476190476190476, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.846984126984127, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1665433n, + refSlot: 1791999n, + frame: [54425, 55999], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.8463492063492063, + threshold: 0.8958714685009193, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1763112600, + endTimestamp: 1763717016, + receivedRewards: 0n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9980952380952381, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9976354679802956, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 9, + validatorIndex: '1208844', + performance: 1, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9980952380952381, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9980952380952381, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 1017064882280122n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 1032299635191559n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9980952380952381, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 17, + validatorIndex: '1208852', + performance: 1, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9994088669950739, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 27, + validatorIndex: '1208862', + performance: 1, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9980952380952381, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9988177339901477, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 32, + validatorIndex: '1208867', + performance: 1, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9980952380952381, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9980952380952381, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9980952380952381, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 42, + validatorIndex: '1208877', + performance: 1, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9993650793650793, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 46, + validatorIndex: '1208881', + performance: 1, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9974603174603175, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9980952380952381, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1618521n, + refSlot: 1741599n, + frame: [52850, 54424], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9987301587301587, + threshold: 0.8866196549913157, + slashed: false, + receivedShares: 593449286866941n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1762507800, + endTimestamp: 1763112216, + receivedRewards: 602338644280027n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 1, + validatorIndex: '1208836', + performance: 1, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 5, + validatorIndex: '1208840', + performance: 1, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9974603174603175, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 11, + validatorIndex: '1208846', + performance: 1, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 1358651683573976n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 1379003111543403n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9974603174603175, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9988177339901477, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9980952380952381, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9974603174603175, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9988177339901477, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9987301587301587, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9993650793650793, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 48, + validatorIndex: '1208883', + performance: 1, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1572159n, + refSlot: 1691199n, + frame: [51275, 52849], + indexInReport: 49, + validatorIndex: '1208884', + performance: 1, + threshold: 0.9041567429297159, + slashed: false, + receivedShares: 792762474415545n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1761903000, + endTimestamp: 1762507416, + receivedRewards: 804637371116436n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9168253968253969, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9149206349206348, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9142857142857141, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9161904761904762, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9174603174603173, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9174603174603173, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9149206349206348, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9174603174603173, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9155555555555556, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9187301587301587, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 2960941440395666n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 3005293784101148n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9225615763546798, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 2960941440395666n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 3005293784101148n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9187301587301587, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 2960941440395666n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 3005293784101148n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9161904761904762, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9149206349206348, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.918095238095238, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 2960941440395666n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 3005293784101148n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9168253968253969, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.918095238095238, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9155555555555556, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9187301587301587, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9168253968253969, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.918095238095238, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9142857142857141, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9130158730158731, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9161904761904762, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9161904761904762, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9168253968253969, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.918095238095238, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9187301587301587, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.918095238095238, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.918423645320197, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9155555555555556, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9168253968253969, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9161904761904762, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9174603174603173, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.918095238095238, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9174603174603173, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9161904761904762, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9161904761904762, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9155555555555556, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9225615763546798, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.923743842364532, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9213793103448276, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9155555555555556, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9174603174603173, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9188302095031561, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9174603174603173, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9174603174603173, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9187301587301587, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9193650793650794, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 1727685830935630n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 1753565071485051n, + }, + { + blockNumber: 1524861n, + refSlot: 1640799n, + frame: [49700, 51274], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9174603174603173, + threshold: 0.9176923237837359, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1761298200, + endTimestamp: 1761902616, + receivedRewards: 0n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9911111111111112, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9904761904761905, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9923809523809524, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9898412698412699, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9923809523809524, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9885714285714285, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9949206349206349, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9904761904761905, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9898412698412699, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9904761904761905, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9898412698412699, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9892063492063492, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.993015873015873, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9949206349206349, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9961904761904762, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9961904761904762, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 1165228169683552n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 1182682280586268n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9917460317460317, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9949206349206349, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9904761904761905, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9911111111111112, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9949206349206349, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9942857142857143, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.993015873015873, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9929064039408867, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9911111111111112, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9873015873015873, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9936507936507937, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9958620689655172, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.993015873015873, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9885714285714285, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9904761904761905, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9917460317460317, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9942857142857143, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9892063492063492, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9917460317460317, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9923809523809524, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9917460317460317, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9885714285714285, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9936507936507937, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9961904761904762, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9923152709359605, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9873015873015873, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9911111111111112, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9961904761904762, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9883308619815038, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9885714285714285, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9923809523809524, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9917460317460317, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9879365079365079, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1478601n, + refSlot: 1590399n, + frame: [48125, 49699], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9936507936507937, + threshold: 0.9188928928826873, + slashed: false, + receivedShares: 679901389167736n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1760693400, + endTimestamp: 1761297816, + receivedRewards: 690085724354781n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9936507936507937, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9936507936507937, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9942857142857143, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9923809523809524, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9942857142857143, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9961904761904762, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9936507936507937, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.993015873015873, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9936507936507937, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9936507936507937, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9936507936507937, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.994088669950739, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 1435293025283508n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 1456792474312445n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9968253968253968, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9917460317460317, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9936507936507937, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9955555555555555, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9942857142857143, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9936507936507937, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9955555555555555, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9974603174603175, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9961904761904762, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9980952380952381, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9974603174603175, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9923152709359605, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9942857142857143, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9955555555555555, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9917460317460317, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9942857142857143, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9904761904761905, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9961904761904762, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9968253968253968, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9923809523809524, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9942857142857143, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9961904761904762, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9904761904761905, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9898412698412699, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9968253968253968, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.994088669950739, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9968253968253968, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9917460317460317, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1431724n, + refSlot: 1539999n, + frame: [46550, 48124], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9949206349206349, + threshold: 0.8776934372451525, + slashed: false, + receivedShares: 837482089038440n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1760088600, + endTimestamp: 1760693016, + receivedRewards: 850026846916277n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9917460317460317, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9961904761904762, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9949206349206349, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9911111111111112, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9980952380952381, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9961904761904762, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9949206349206349, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9961904761904762, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9942857142857143, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9974603174603175, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 1089409926812705n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 1105728345965130n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9911111111111112, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9974603174603175, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9961904761904762, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9949206349206349, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.993015873015873, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.994679802955665, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9949206349206349, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9949206349206349, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9942857142857143, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9949206349206349, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9923809523809524, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9961904761904762, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9936507936507937, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9974603174603175, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9949206349206349, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9993650793650793, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9949206349206349, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9942857142857143, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9955555555555555, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9968253968253968, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1384995n, + refSlot: 1489599n, + frame: [44975, 46549], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9942857142857143, + threshold: 0.8667586900075089, + slashed: false, + receivedShares: 635662046184683n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1759483800, + endTimestamp: 1760088216, + receivedRewards: 645183714248859n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9619047619047619, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9580952380952381, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9580952380952381, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9542857142857143, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.954920634920635, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9574603174603175, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9574603174603175, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9587301587301588, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9587301587301588, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9555555555555556, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9574603174603175, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.954920634920635, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.96, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 910759601308275n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 924401992987894n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9561904761904761, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9574603174603175, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9587301587301588, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9587301587301588, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.96, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.96, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9593650793650793, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9574603174603175, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9593650793650793, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9574603174603175, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9621674876847289, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9587301587301588, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.954920634920635, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.961576354679803, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9587301587301588, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9606349206349206, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9587301587301588, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9580952380952381, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9586206896551724, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9542857142857143, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9593650793650793, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9593650793650793, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9574603174603175, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9574603174603175, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9625396825396826, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.954920634920635, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9568253968253968, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1339103n, + refSlot: 1439199n, + frame: [43400, 44974], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9580952380952381, + threshold: 0.8933141892512583, + slashed: false, + receivedShares: 531420999112574n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1758879000, + endTimestamp: 1759483416, + receivedRewards: 539381226384681n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9892063492063492, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9923809523809524, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9879365079365079, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9898412698412699, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9955555555555555, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9961904761904762, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9917460317460317, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9936507936507937, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.993015873015873, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.986031746031746, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9917460317460317, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.993015873015873, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9936507936507937, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9942857142857143, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9955555555555555, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9917460317460317, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 954444704203379n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 968741460968365n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9923809523809524, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9961904761904762, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9942857142857143, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9936507936507937, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9936507936507937, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9892063492063492, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9949206349206349, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9904761904761905, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9936507936507937, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9955555555555555, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9942857142857143, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9923809523809524, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9936507936507937, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9917460317460317, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9904761904761905, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9911111111111112, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9898412698412699, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.993015873015873, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9917460317460317, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9923809523809524, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9942857142857143, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9923809523809524, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.993015873015873, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.986031746031746, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9898412698412699, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9923809523809524, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9892063492063492, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9885714285714285, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9923809523809524, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9911111111111112, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9949206349206349, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9885714285714285, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9923809523809524, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1291862n, + refSlot: 1388799n, + frame: [41825, 43399], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9936507936507937, + threshold: 0.8939854806534347, + slashed: false, + receivedShares: 556910909944702n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1758274200, + endTimestamp: 1758878616, + receivedRewards: 565252954050748n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.993015873015873, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9968253968253968, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9970443349753695, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9980952380952381, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9961904761904762, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9955555555555555, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9961904761904762, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9942857142857143, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9968253968253968, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9942857142857143, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9968253968253968, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9993650793650793, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9961904761904762, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9987301587301587, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9942857142857143, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9968253968253968, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 1156233911110820n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 1173553295793642n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9955555555555555, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9942857142857143, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9974603174603175, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9974603174603175, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9961904761904762, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9961904761904762, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9955555555555555, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9980952380952381, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9949206349206349, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9961904761904762, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9949206349206349, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9955555555555555, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9968253968253968, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9949206349206349, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9949206349206349, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9974603174603175, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9955555555555555, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.993015873015873, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9968253968253968, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9955555555555555, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9961904761904762, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9974603174603175, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9968253968253968, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9968253968253968, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9974603174603175, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9980952380952381, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9961904761904762, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9968253968253968, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9942857142857143, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9987301587301587, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9936507936507937, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9936507936507937, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9974603174603175, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1244138n, + refSlot: 1338399n, + frame: [40250, 41824], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9980952380952381, + threshold: 0.8866556657660963, + slashed: false, + receivedShares: 674653310673551n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1757669400, + endTimestamp: 1758273816, + receivedRewards: 684759034180543n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9987301587301587, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9955555555555555, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9987301587301587, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9955555555555555, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9987301587301587, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9974603174603175, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9987301587301587, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.99690566602443, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9993650793650793, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9970443349753695, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 949574207630139n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 963798008565913n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9974603174603175, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9974603174603175, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9968253968253968, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9987301587301587, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9974603174603175, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9993650793650793, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9961904761904762, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9961904761904762, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9974603174603175, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9968253968253968, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9987301587301587, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9949206349206349, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9974603174603175, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 30, + validatorIndex: '1208865', + performance: 1, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9974603174603175, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9974603174603175, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9955555555555555, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9955555555555555, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9968253968253968, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9961904761904762, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9993650793650793, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9955555555555555, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9987301587301587, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9968253968253968, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9980952380952381, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9987301587301587, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9968253968253968, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9987301587301587, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9949206349206349, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1196669n, + refSlot: 1287999n, + frame: [38675, 40249], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9974603174603175, + threshold: 0.8754885952595604, + slashed: false, + receivedShares: 554069013848951n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1757064600, + endTimestamp: 1757669016, + receivedRewards: 562368488807666n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9988177339901477, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9974603174603175, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 3, + validatorIndex: '1208838', + performance: 1, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9987301587301587, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 6, + validatorIndex: '1208841', + performance: 1, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9974603174603175, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9974603174603175, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9961904761904762, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9961904761904762, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9974603174603175, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9961904761904762, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9993650793650793, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 1331633955846282n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 1351580681605131n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9968253968253968, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9955555555555555, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9974603174603175, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9974603174603175, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9993650793650793, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9987301587301587, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9961904761904762, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9961904761904762, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9976354679802956, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 31, + validatorIndex: '1208866', + performance: 1, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9994088669950739, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9961904761904762, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9987301587301587, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9994088669950739, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9993650793650793, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9961904761904762, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9961904761904762, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9987301587301587, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9974603174603175, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9968253968253968, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9987301587301587, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9974603174603175, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9980952380952381, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9993650793650793, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1149935n, + refSlot: 1237599n, + frame: [37100, 38674], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9987301587301587, + threshold: 0.8843533408547883, + slashed: false, + receivedShares: 776997844712846n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1756459800, + endTimestamp: 1757064216, + receivedRewards: 788636600885787n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.9968253968253968, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9961904761904762, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9974603174603175, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.9987301587301587, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9987301587301587, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9974603174603175, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9968253968253968, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9942857142857143, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9968253968253968, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9993650793650793, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9961904761904762, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9987301587301587, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 1365362365816994n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 1385814314006538n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9955555555555555, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9961904761904762, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9974603174603175, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9993650793650793, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9961904761904762, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9993650793650793, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9955555555555555, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9968253968253968, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9955555555555555, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9974603174603175, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9968253968253968, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9961904761904762, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9993650793650793, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9961904761904762, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9974603174603175, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9974603174603175, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9974603174603175, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9968253968253968, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9961904761904762, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.9955555555555555, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9987301587301587, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9968253968253968, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9987301587301587, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9968253968253968, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9980952380952381, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9955555555555555, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1103716n, + refSlot: 1187199n, + frame: [35525, 37099], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9968253968253968, + threshold: 0.8814908205270398, + slashed: false, + receivedShares: 796678104244964n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1755855000, + endTimestamp: 1756459416, + receivedRewards: 808611653696513n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 0, + validatorIndex: '1208835', + performance: 0.9869130100076983, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 745360238297212n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x96b50ceb53f7c7ff417b02a605c811ffe9cfba3d0e4f0183e79144f00c32958fbea88d23afd7fe9b67b50a2a36ea590b', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 756525090469682n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 1, + validatorIndex: '1208836', + performance: 0.985373364126251, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 745360238297212n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2e70be2acbb553ebadd271734967c65c3208600d8639fe4fa6c79e27b62c07c04b23d7a73e90a9b90d29b42c445831b', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 756525090469682n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 2, + validatorIndex: '1208837', + performance: 0.9869130100076983, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 745360238297212n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa60b7d36c1bfb0375530de7953a4f8ae9e7be7e784ea87b4c2c92d128bbf3d23362ebe4e7fbb869d149a38a039bacc02', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 756525090469682n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 3, + validatorIndex: '1208838', + performance: 0.9869130100076983, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 745360238297212n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa251beba8d4374629e322829a42a24be1028ebdbd98585bd29700bf9460a817d3689d528cfaf0fc24db9840e187f170b', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 756525090469682n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 4, + validatorIndex: '1208839', + performance: 0.984937038414537, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744786442886668n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89b02b07c17f3a59bec3bb894bf178bfa8526137ffcfdc0a83500c97242bba9f61213720e9ee7937d99e18071b021743', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755942700099806n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 5, + validatorIndex: '1208840', + performance: 0.9838212634822804, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744786442886668n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb76198b2a7fbd01b46c90686a087e4e6dd9f7acd2b632fce1a60e5d4dca53840a212564f2c51f2ed15ad3796f1d005f7', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755942700099806n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 6, + validatorIndex: '1208841', + performance: 0.9838212634822804, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744786442886668n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x912b63602d7b45a4c61218b569b5514a9f835a04fe39acad56b79a268778e22821af17103f01d612f70117056589a852', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755942700099806n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 7, + validatorIndex: '1208842', + performance: 0.9884437596302003, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744786442886668n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9962daae1d4386f25e1c2834d5a6a75a11a616cedde1751c5137deca3d4f99dc3151b3e96fa7e9ff6407f705a7164654', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755942700099806n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 8, + validatorIndex: '1208843', + performance: 0.9845916795069337, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744786442886668n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x910b5d124c3e7b87c89339bc455f7aec7f5df6129a9597027cd2fa61d9fa92b2b310b0a9fa05365b8941258ded673907', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755942700099806n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 9, + validatorIndex: '1208844', + performance: 0.9870888900696031, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744786442886668n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ebd216c87a584b55531e6a2aa94067e1cc60b58aa6bee32356d901e1b73701b4df7cc5c67e824cf2fe0bf102bb3fd37', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755942700099806n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 10, + validatorIndex: '1208845', + performance: 0.9869029275808937, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744786442886668n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8343fd66edac0647585dbb476b32664c586e2cd27af432577ab62f7e6fb2163bb8d83eb7622d67d8e779dbbd7dd8e4d5', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755942700099806n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 11, + validatorIndex: '1208846', + performance: 0.9876733436055471, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744786442886668n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7e276918d1a63ccf910e71c3b3c13a897e493703fd4a3691a2a7f870f4a283cba81fcff6b5893f3a7b9054fcc9276f1', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755942700099806n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 12, + validatorIndex: '1208847', + performance: 0.9868928296067849, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744212647476123n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x93fb914d0e4569281db8fb4a1dd5ade5f7e20e466c063e383cb7d925ba027328edec85a370c9c730e0579d3b99c51d75', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755360309729928n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 13, + validatorIndex: '1208848', + performance: 0.9845797995373938, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744212647476123n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa44c875cadb87eddb33f9c0be0ee0f854791fd6cde2f8e3f2660fb743108e208ef00e254f606a5fa04851d292cbfeb5e', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755360309729928n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 14, + validatorIndex: '1208849', + performance: 0.9856432616382633, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744212647476123n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x901da150ea14e7ce633ce96310acdcf65f9bc04450bd1a01dc1f605c67db1a56e87d3fcb3ddafc7393af295e28e675b2', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755360309729928n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 15, + validatorIndex: '1208850', + performance: 0.9863610985563501, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 744212647476123n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9542fac145d8d57c2e191a345099198c0e82e6aff76f43cf9bd770643a75d743fba146a2733a70a46a558fae70f49552', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 755360309729928n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 16, + validatorIndex: '1208851', + performance: 0.9849254247201765, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x899dee9bc3f7f61cf1c29e732a1ec3ab7e9fea4889331d8c738f72a839d5f18569a8c273c2f1a78cf5cb27f244d64cc3', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 17, + validatorIndex: '1208852', + performance: 0.9868928296067849, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7ccd697df7e8ffc3686512d43d12ff345ab8d868637696934122879e35a55c9c788d7fc1405ad2a2d992d58060c32d6', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 18, + validatorIndex: '1208853', + performance: 0.9876638396299152, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaeb35d864b393373b4d8f93e9f5dc5560e069f35318344cdf7126c5429c899593630fb53e22896d5e59166739d5090f8', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 19, + validatorIndex: '1208854', + performance: 0.9853508095605242, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3237f1b818b922422c4a4e622cadf64e66c35247c714eac975ac84db72a33687ae966277587401c55d0f548084e5e28', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 20, + validatorIndex: '1208855', + performance: 0.9845679012345679, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91833a85a3bae261d4ef2ea28a6c0cc6fa342c38ed50c3c3b9da810a085328732e658c22be0635480f78845f9d688d7c', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 21, + validatorIndex: '1208856', + performance: 0.9853395061728395, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa1e419c18c161ef094c82170b3e62d8331a6e5970a9530b7a69e6ca21b1bd59d95ca62c61d60cdc5d2beb5b1fa32de54', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 22, + validatorIndex: '1208857', + performance: 0.9868827160493827, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f79cee46b66bf3810e31dd048cc1ec643d05d9c26340e5f1e3e1a8e57ffe0ff203788f98a197ce46b13d221bd39018c', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 23, + validatorIndex: '1208858', + performance: 0.9861111111111112, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x83ebf76e5a085180c34690b0315056e2b01a5a557a12e52c2bb5a7b6618f384a7faab2b8b4fce701a998e2750b531b6e', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 24, + validatorIndex: '1208859', + performance: 0.9861111111111112, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5f0f009b98d21564e545bbeb25b61022b52982e6328c0794797cf470599013ef841073857b8886818a1511a1a6f5092', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 25, + validatorIndex: '1208860', + performance: 0.9868827160493827, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9b7630a464c0f74b25f8a8c95a43906fb6bbb4e05661ae171828d60e1aa337f17fc81257fdf7daeace2549fee10494e', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 26, + validatorIndex: '1208861', + performance: 0.9837962962962963, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa453ffd40f306d9ad57e7f65a96f5e9070f0579524d9175ccfc6e7f7bd4e5635772f41a86d47e8c71847730b7d08b97c', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 27, + validatorIndex: '1208862', + performance: 0.9885057471264367, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 434363125782132n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xab5ac2f98c2dfecfe344c2c7ef05ab7f99933d8c05afc13914ccd6f514ea78557b31f4faab62a13af0a92dde8cd6823a', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440869509996573n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 28, + validatorIndex: '1208863', + performance: 0.9884169884169884, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433789330371587n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8bc280c0c93e5411907e10b072fb2ecedcd71fd14d87af7a361ad9d01c85846063e384eb8c5ace0a7374459d0698a6e5', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440287119626696n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 29, + validatorIndex: '1208864', + performance: 0.9891891891891892, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433789330371587n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb54adcc2fe57ef81d3a1d6417850ac1653a63c0cecc50515ea236e4a269bb585dc497aa36aef8f144a5edde7a040f019', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440287119626696n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 30, + validatorIndex: '1208865', + performance: 0.9876447876447877, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433789330371587n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9456f57d3066290e9f72502ff862d510a945f810d8fee8e7a1cad435e08f8a848eed1eac093bb5bedf6aeec7a89ede0', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440287119626696n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 31, + validatorIndex: '1208866', + performance: 0.9861003861003861, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433789330371587n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb87371c94cc6e034b4ad807fe51dbfa057bdeb94a08df5f7cd36f8aa19e1c771b56319e18aa06f0540cef65f1a9d553b', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440287119626696n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 32, + validatorIndex: '1208867', + performance: 0.9861003861003861, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433789330371587n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8269b2a2a236a33a8c9434c3ff9e463f0fc64b750cfeeaa3b2b891b5dfb3a3dca22d9bd1877ce3abc3e09a4affd5e9c5', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440287119626696n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 33, + validatorIndex: '1208868', + performance: 0.9853281853281852, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433789330371587n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x90243dcacd6af03bf0f73d969f3db38368af68cbd13e95edda97af3e2409412a5757c0c8e6c8860b0c8fb32cc2e83382', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440287119626696n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 34, + validatorIndex: '1208869', + performance: 0.9876447876447877, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433789330371587n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87c2097c5b6eca870d003098989b70ee4187a44c4be4945bc7ca05848f72ab23c3c73e28c6a6d6d64e70c551acfb5cb1', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440287119626696n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 35, + validatorIndex: '1208870', + performance: 0.9868725868725868, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433789330371587n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85f6aee1e89b148c995b81dc3eb3bb5c29cc403874d783f1ae46e0c09cb70d29a5879b472fe02d21e7164285f1fd4d3a', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 440287119626696n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 36, + validatorIndex: '1208871', + performance: 0.9876352395672334, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaaae01c4af488638635329f50af355045754e6c0b50b9ae9c8cde1396629a7f19d5e1a2883cd7df56b006612b30fe07b', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 37, + validatorIndex: '1208872', + performance: 0.9853168469860897, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x896e49d476399977670ae9e65e330f0da78aab8d496d3b91ec01ed9ace196989e260ef10e9da76d268356acd957185fc', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 38, + validatorIndex: '1208873', + performance: 0.9868624420401854, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb70b9d747f226fc2a74e3da9fcf3ee240edb1d926b7d00dbe4b87442391a74b8e85a4653dd44fc6fdfb0f7a187d9ec52', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 39, + validatorIndex: '1208874', + performance: 0.9876352395672334, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa5f3038042f8a957b71dcdc3c6870a0635523fdbd9634d5c72d30cc9cefebae3f95e96056cc450e5dd569bd474e40d41', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 40, + validatorIndex: '1208875', + performance: 0.9868624420401854, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x85084c60e15ffae0fd5eb9b8635857153fae89ff8e122a288e04c33916e45737db53f3d86d5f4b85b1705685691ab04e', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 41, + validatorIndex: '1208876', + performance: 0.9876352395672334, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb88bb8704f830ed44bf210696f2e97025c6f2c80514c0e1c18313e5737646fa5fe33b94efb58831de1de250c5df1b6ee', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 42, + validatorIndex: '1208877', + performance: 0.982225656877898, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb81aec2fb71f79bd705c195be85132122ffdf39bccf791652159c4fe58c6651fa0f26d2a65602fb24ef43da32f65505d', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 43, + validatorIndex: '1208878', + performance: 0.9868624420401854, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x92f78443f4e2bdb161389be093e8c1056d24b2957ab7ad33fe800ab26b8db9b21b9051a481c7a9ff0c912f960fe6934b', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 44, + validatorIndex: '1208879', + performance: 0.9860788863109049, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb5ccffcd15fdd75a098922d37155c7426ae85f35d9c2f1a52fc5fd7b1b2b5746084bdae3c753363a0941d1708e2a7a6b', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 45, + validatorIndex: '1208880', + performance: 0.9877590207216577, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8e825d2fcf9db0a1fefa218ab9de1de9ad5af39be4e99dd80e82e0548937b75690e5cf7293f1023204937252dcfebcfd', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 46, + validatorIndex: '1208881', + performance: 0.9860788863109049, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8831ad5099146979f4fcd95173b48f806f1914456490e838699c3baf21d5ed7c194a84b279b3fd28c23d62535aca50b9', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 47, + validatorIndex: '1208882', + performance: 0.9853054911059551, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb95a8f51b29a2ddf163c763ccaaa1b95f06b674cd0d2fcdf04a7b2b30d12f393a0571238fa04c3b2d69e36c8355a880f', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 48, + validatorIndex: '1208883', + performance: 0.9868522815158545, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb1cf388ca03cb6086e32337466286d4b89da1987277112a3f9e62010d81f65d2fb972b023984e77e5a495b63ea4c7e2d', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 1057022n, + refSlot: 1136799n, + frame: [33950, 35524], + indexInReport: 49, + validatorIndex: '1208884', + performance: 0.9860788863109049, + threshold: 0.8683770272131761, + slashed: false, + receivedShares: 433215534961043n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x840d25d63fc2d5e66db1e55b63b38ed1736b5642fba94ad600dc04365365deb4ca46d2a2a73fad73980dfc8b7683cafd', + startTimestamp: 1755250200, + endTimestamp: 1755854616, + receivedRewards: 439704729256820n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.9939879759519038, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 745953198047151n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 757126932244194n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.996993987975952, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 745953198047151n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 757126932244194n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.996993987975952, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 745953198047151n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 757126932244194n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.9959879638916749, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.9949899799599199, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 745953198047151n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 757126932244194n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.996993987975952, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 745953198047151n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 757126932244194n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.996993987975952, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 745953198047151n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 757126932244194n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.9939879759519038, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 745953198047151n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 757126932244194n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.9979939819458375, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.995983935742972, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.9969909729187563, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.995983935742972, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.9969909729187563, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.9979939819458375, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.9969879518072289, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.9979939819458375, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.9969879518072289, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.9959879638916749, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.9959879638916749, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.998995983935743, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.9979899497487437, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 743394181930352n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 754529584277662n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 743394181930352n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 754529584277662n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.9991246555357433, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 743394181930352n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 754529584277662n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.998995983935743, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.998995983935743, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.998995983935743, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 744673689988752n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 755828258260928n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.9979899497487437, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 743394181930352n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 754529584277662n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.9979899497487437, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 743394181930352n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 754529584277662n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.9939698492462311, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 743394181930352n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 754529584277662n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.9959758551307846, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 742114673871952n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 753230910294396n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.9989939637826962, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 742114673871952n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 753230910294396n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.9929577464788731, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 742114673871952n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 753230910294396n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.9959758551307846, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 742114673871952n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 753230910294396n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.9949748743718593, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 743394181930352n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 754529584277662n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.9949698189134809, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 742114673871952n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 753230910294396n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.9949698189134809, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 742114673871952n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 753230910294396n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.9964986221429729, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 743394181930352n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 754529584277662n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.9989939637826962, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 742114673871952n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 753230910294396n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.9969818913480886, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 742114673871952n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 753230910294396n, + }, + { + blockNumber: 964733n, + refSlot: 1035999n, + frame: [30800, 32374], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.996491570022415, + threshold: 0.861580548499018, + slashed: false, + receivedShares: 742114673871952n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1754040600, + endTimestamp: 1754645016, + receivedRewards: 753230910294396n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.5853968253968254, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.5815873015873015, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.5834920634920635, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.586031746031746, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.6383410138248848, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.5828571428571429, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.5866666666666667, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.5828571428571429, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.5841269841269842, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.586031746031746, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.5822222222222222, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.5866666666666667, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.5873015873015873, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.5098617511520737, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.5841269841269842, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.5866666666666667, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.5866666666666667, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.587936507936508, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.5847619047619048, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.5828571428571429, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.5847619047619048, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.5815873015873015, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.5841269841269842, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.5873015873015873, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.5828571428571429, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.5828571428571429, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.5841269841269842, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.5796825396825397, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.5873015873015873, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.5873015873015873, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.64, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.5834920634920635, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.587936507936508, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.5866666666666667, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.5828571428571429, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.5853968253968254, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.5873015873015873, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.5841269841269842, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.5841269841269842, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 919718n, + refSlot: 985599n, + frame: [29225, 30799], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.5866666666666667, + threshold: 0.8595734901882666, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1753435800, + endTimestamp: 1754040216, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.7428571428571429, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.7479365079365079, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.7498412698412699, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.7333333333333333, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.753015873015873, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.7619047619047619, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.7346031746031746, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.7473015873015874, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.7453968253968254, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.7485714285714286, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.7631746031746032, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.7523809523809524, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.7441269841269841, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.758095238095238, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.7123809523809522, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.7396825396825397, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.7568253968253968, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.7593650793650794, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.7447619047619047, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.7352380952380952, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.7409523809523809, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.7326984126984127, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.7396825396825397, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.7434920634920635, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.6442396313364055, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.7492063492063492, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.7447619047619047, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.7485714285714286, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.753015873015873, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.7587301587301587, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.7390476190476191, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.7542857142857143, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.7409523809523809, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.7358730158730159, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.7561904761904762, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.7447619047619047, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.7396825396825397, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.7415873015873016, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.7326984126984127, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 874957n, + refSlot: 935199n, + frame: [27650, 29224], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.7536507936507937, + threshold: 0.9004204082047349, + slashed: false, + receivedShares: 0n, + rewardShare: 0.5834, + fee: 350n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1752831000, + endTimestamp: 1753435416, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.7663492063492063, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.7860317460317461, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.7695238095238095, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.7784126984126984, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.7847619047619048, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.7942857142857143, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.7707936507936508, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.7746031746031746, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.7777777777777778, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.7847619047619048, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.7942857142857143, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.7771428571428571, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.7930158730158731, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.7841269841269841, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.7682539682539683, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.7828571428571428, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.7923809523809524, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.7930158730158731, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.7873015873015873, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.8063492063492064, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.7879365079365079, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.7828571428571428, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.7955555555555556, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.7815873015873016, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.7847619047619048, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.7898412698412698, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.7707936507936508, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.7853968253968254, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.7930158730158731, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.7631746031746032, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.7790476190476191, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.7911111111111111, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.7688888888888888, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.7695238095238095, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.7993650793650794, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.7701587301587302, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.8031746031746032, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.7568253968253968, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.780952380952381, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 828055n, + refSlot: 884799n, + frame: [26075, 27649], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.7720634920634921, + slashed: false, + threshold: 0.8750877807223604, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1752226200, + endTimestamp: 1752830616, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.8482539682539683, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.8634920634920635, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.8546031746031746, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.8711111111111111, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.8450793650793651, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.8552380952380952, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.8565079365079366, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.8596825396825397, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.8647619047619047, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.8419047619047619, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.8482539682539683, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.8641269841269841, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.8565079365079366, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.8634920634920635, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.846984126984127, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.8546031746031746, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.8419047619047619, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.8552380952380952, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.8571428571428571, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.8641269841269841, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.8571428571428571, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.846984126984127, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.8476190476190476, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.8501587301587301, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.8641269841269841, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.866031746031746, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.8590476190476191, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.8501587301587301, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.8514285714285714, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.8482539682539683, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.8615873015873016, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.8539682539682539, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.8584126984126984, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.8596825396825397, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.8514285714285714, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.8615873015873016, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.8615873015873016, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 781669n, + refSlot: 834399n, + frame: [24500, 26074], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.889175728680915, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1751621400, + endTimestamp: 1752225816, + receivedRewards: 0n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.9574603174603175, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.9587301587301588, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.9492063492063492, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.9542857142857143, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.9517460317460318, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.9511111111111111, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.9523809523809523, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.953015873015873, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.9574603174603175, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.9447619047619048, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.9580952380952381, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.9517460317460318, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.9542857142857143, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.9555555555555556, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.9434920634920635, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.9504761904761905, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.953015873015873, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.9542857142857143, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.9536507936507936, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.9523809523809523, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.9473015873015873, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.9453968253968253, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.9625396825396826, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.9568253968253968, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.9561904761904761, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.947936507936508, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.9561904761904761, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.9542857142857143, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.9504761904761905, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.9377777777777778, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.9574603174603175, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.9593650793650793, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.9631746031746031, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.953015873015873, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.9511111111111111, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.9466666666666667, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.9511111111111111, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.9587301587301588, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.9498412698412698, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 734459n, + refSlot: 783999n, + frame: [22925, 24499], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.9492063492063492, + slashed: false, + threshold: 0.896760201235149, + receivedShares: 2462530754806021n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1751016600, + endTimestamp: 1751621016, + receivedRewards: 2499417337205936n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.9733333333333334, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.9777777777777777, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.9682539682539683, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.9771428571428571, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.9733333333333334, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.9720634920634921, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.9644444444444444, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.9650793650793651, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.9720634920634921, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.9676190476190476, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.9758730158730159, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.9765079365079365, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.96, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.9644444444444444, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.9688888888888889, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.9695238095238096, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.9726984126984127, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.9726984126984127, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.966984126984127, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.9701587301587301, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.9714285714285714, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.9771428571428571, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.9707936507936508, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.9650793650793651, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.9746031746031746, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.979047619047619, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.9726984126984127, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.9701587301587301, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.9733333333333334, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.9676190476190476, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.9695238095238096, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.9803174603174604, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.9676190476190476, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.9650793650793651, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.9714285714285714, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.9758730158730159, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.9631746031746031, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.9733333333333334, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.966984126984127, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 687265n, + refSlot: 733599n, + frame: [21350, 22924], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.9752380952380952, + slashed: false, + threshold: 0.8846745835037102, + receivedShares: 2697135663094124n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1750411800, + endTimestamp: 1751016216, + receivedRewards: 2737536424256722n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 640719n, + refSlot: 683199n, + frame: [19775, 21349], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.879074545557767, + receivedShares: 2782938543355590n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749807000, + endTimestamp: 1750411416, + receivedRewards: 2824624557507105n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.9822222222222222, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.9822222222222222, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.9822222222222222, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.9822222222222222, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.9822222222222222, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.9866666666666667, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 594012n, + refSlot: 632799n, + frame: [19550, 19774], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.9822222222222222, + slashed: false, + threshold: 0.8875317067211371, + receivedShares: 133926289392718n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749720600, + endTimestamp: 1749806616, + receivedRewards: 135932389458497n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 587262n, + refSlot: 625599n, + frame: [19325, 19549], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8901933161325853, + receivedShares: 149860683245736n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749634200, + endTimestamp: 1749720216, + receivedRewards: 152105466759713n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 580522n, + refSlot: 618399n, + frame: [19100, 19324], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8905730512140176, + receivedShares: 153966144311356n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749547800, + endTimestamp: 1749633816, + receivedRewards: 156272424083843n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 573755n, + refSlot: 611199n, + frame: [18875, 19099], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8767184543255041, + receivedShares: 136045336398940n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749461400, + endTimestamp: 1749547416, + receivedRewards: 138083177957430n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 567067n, + refSlot: 603999n, + frame: [18650, 18874], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8916643257003238, + receivedShares: 125308990763680n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749375000, + endTimestamp: 1749461016, + receivedRewards: 127186011143723n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 560336n, + refSlot: 596799n, + frame: [18425, 18649], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.891682081156182, + receivedShares: 117038158572418n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749288600, + endTimestamp: 1749374616, + receivedRewards: 118791289034520n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 553584n, + refSlot: 589599n, + frame: [18200, 18424], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8665184439964809, + receivedShares: 107707743890546n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749202200, + endTimestamp: 1749288216, + receivedRewards: 109321112804771n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 546967n, + refSlot: 582399n, + frame: [17975, 18199], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8930991708346596, + receivedShares: 412526672641962n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749115800, + endTimestamp: 1749201816, + receivedRewards: 418705965661093n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 540206n, + refSlot: 575199n, + frame: [17750, 17974], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8932230720005178, + receivedShares: 409604258448911n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1749029400, + endTimestamp: 1749115416, + receivedRewards: 415739776229204n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 533421n, + refSlot: 567999n, + frame: [17525, 17749], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8930527038711789, + receivedShares: 414590262635028n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748943000, + endTimestamp: 1749029016, + receivedRewards: 420800466448744n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 526606n, + refSlot: 560799n, + frame: [17300, 17524], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8883777228638527, + receivedShares: 409037215106440n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748856600, + endTimestamp: 1748942616, + receivedRewards: 415164239067545n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 519814n, + refSlot: 553599n, + frame: [17075, 17299], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.879933011417823, + receivedShares: 413363395664534n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748770200, + endTimestamp: 1748856216, + receivedRewards: 419555222071384n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 513094n, + refSlot: 546399n, + frame: [16850, 17074], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8794910021408028, + receivedShares: 418728405475535n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748683800, + endTimestamp: 1748769816, + receivedRewards: 425000595092502n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.8622222222222222, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.8577777777777778, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 506368n, + refSlot: 539199n, + frame: [16625, 16849], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.8533333333333334, + slashed: false, + threshold: 0.878442417250298, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748597400, + endTimestamp: 1748683416, + receivedRewards: 0n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 499629n, + refSlot: 531999n, + frame: [16400, 16624], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8509259349474171, + receivedShares: 126188362422922n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748511000, + endTimestamp: 1748597016, + receivedRewards: 128078555030400n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 493136n, + refSlot: 524799n, + frame: [16175, 16399], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8491236161872734, + receivedShares: 130018002511091n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748424600, + endTimestamp: 1748510616, + receivedRewards: 131965559817223n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 486630n, + refSlot: 517599n, + frame: [15950, 16174], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8743899804766133, + receivedShares: 135914215915462n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748338200, + endTimestamp: 1748424216, + receivedRewards: 137950093402433n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 479928n, + refSlot: 510399n, + frame: [15725, 15949], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8788101027226957, + receivedShares: 131430887734509n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748251800, + endTimestamp: 1748337816, + receivedRewards: 133399608840164n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 473227n, + refSlot: 503199n, + frame: [15500, 15724], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8949525516117758, + receivedShares: 132637618020565n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748165400, + endTimestamp: 1748251416, + receivedRewards: 134624414902957n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 466412n, + refSlot: 495999n, + frame: [15275, 15499], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8938482738722414, + receivedShares: 136836419756441n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1748079000, + endTimestamp: 1748165016, + receivedRewards: 138886111059911n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 459566n, + refSlot: 488799n, + frame: [15050, 15274], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8967540580074835, + receivedShares: 135843207500620n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747992600, + endTimestamp: 1748078616, + receivedRewards: 137878021342908n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 452801n, + refSlot: 481599n, + frame: [14825, 15049], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8940330663580174, + receivedShares: 152268357979869n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747906200, + endTimestamp: 1747992216, + receivedRewards: 154549206380467n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 445964n, + refSlot: 474399n, + frame: [14600, 14824], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8926933368168322, + receivedShares: 210964742258317n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747819800, + endTimestamp: 1747905816, + receivedRewards: 214124811765510n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 439189n, + refSlot: 467199n, + frame: [14375, 14599], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9023006521611854, + receivedShares: 150058361179756n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747733400, + endTimestamp: 1747819416, + receivedRewards: 152306105738336n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 432288n, + refSlot: 459999n, + frame: [14150, 14374], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9146404668659412, + receivedShares: 151023450423416n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747647000, + endTimestamp: 1747733016, + receivedRewards: 153285651184763n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 425360n, + refSlot: 452799n, + frame: [13925, 14149], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9156643992865872, + receivedShares: 188583027899932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747560600, + endTimestamp: 1747646616, + receivedRewards: 191407838670023n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 418381n, + refSlot: 445599n, + frame: [13700, 13924], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9173697806691302, + receivedShares: 140129435915516n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747474200, + endTimestamp: 1747560216, + receivedRewards: 142228453754973n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 411414n, + refSlot: 438399n, + frame: [13475, 13699], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9173451933093008, + receivedShares: 153985088123233n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747387800, + endTimestamp: 1747473816, + receivedRewards: 156291651657649n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 404444n, + refSlot: 431199n, + frame: [13250, 13474], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9097196832883401, + receivedShares: 145179558933314n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747301400, + endTimestamp: 1747387416, + receivedRewards: 147354223250876n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 397469n, + refSlot: 423999n, + frame: [13025, 13249], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8934010568180702, + receivedShares: 146448926513118n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747215000, + endTimestamp: 1747301016, + receivedRewards: 148642604859941n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 390487n, + refSlot: 416799n, + frame: [12800, 13024], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8615889559943731, + receivedShares: 136773701486765n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747128600, + endTimestamp: 1747214616, + receivedRewards: 138822453324762n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 383696n, + refSlot: 409599n, + frame: [12575, 12799], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.909569852295627, + receivedShares: 139550047813824n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1747042200, + endTimestamp: 1747128216, + receivedRewards: 141640386920269n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 376757n, + refSlot: 402399n, + frame: [12350, 12574], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9147859774239707, + receivedShares: 143011314604254n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1746955800, + endTimestamp: 1747041816, + receivedRewards: 145153500495729n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 369822n, + refSlot: 395199n, + frame: [12125, 12349], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9124693549394833, + receivedShares: 138921759677306n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1746869400, + endTimestamp: 1746955416, + receivedRewards: 141002687570481n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 362906n, + refSlot: 387999n, + frame: [11900, 12124], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.913451488893102, + receivedShares: 150919798716015n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1746783000, + endTimestamp: 1746869016, + receivedRewards: 153180446864368n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 356001n, + refSlot: 380799n, + frame: [11675, 11899], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.916013507519767, + receivedShares: 147846424094951n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1746696600, + endTimestamp: 1746782616, + receivedRewards: 150061035747726n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 349075n, + refSlot: 373599n, + frame: [11450, 11674], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9282213142017781, + receivedShares: 150918095042932n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1746610200, + endTimestamp: 1746696216, + receivedRewards: 153178717671735n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.9991111111111111, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 342041n, + refSlot: 366399n, + frame: [10325, 11449], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9108406249034635, + receivedShares: 686671786002361n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1746178200, + endTimestamp: 1746609816, + receivedRewards: 696957535882495n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 307905n, + refSlot: 330399n, + frame: [10100, 10324], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8810667077897141, + receivedShares: 134082339556826n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1746091800, + endTimestamp: 1746177816, + receivedRewards: 136090777119192n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 301266n, + refSlot: 323199n, + frame: [9875, 10099], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9216368904907527, + receivedShares: 435383673249763n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1746005400, + endTimestamp: 1746091416, + receivedRewards: 441905344383234n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 294369n, + refSlot: 315999n, + frame: [9650, 9874], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9355835293539311, + receivedShares: 150675595068685n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745919000, + endTimestamp: 1746005016, + receivedRewards: 152932585257461n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 3, + validatorIndex: '1062301', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 4, + validatorIndex: '1062302', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 8, + validatorIndex: '1062306', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 11, + validatorIndex: '1062309', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 17, + validatorIndex: '1062315', + performance: 0.5377777777777778, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 18, + validatorIndex: '1062316', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.5377777777777778, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.5377777777777778, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 36, + validatorIndex: '1062772', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 38, + validatorIndex: '1062774', + performance: 0.5466666666666666, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 287382n, + refSlot: 308799n, + frame: [9425, 9649], + indexInReport: 39, + validatorIndex: '1062775', + performance: 0.5422222222222223, + slashed: false, + threshold: 0.9267488802215939, + receivedShares: 0n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745832600, + endTimestamp: 1745918616, + receivedRewards: 0n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 0, + validatorIndex: '1062298', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 25, + validatorIndex: '1062323', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 27, + validatorIndex: '1062325', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 280437n, + refSlot: 301599n, + frame: [9200, 9424], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9096036133950539, + receivedShares: 132294468261822n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745746200, + endTimestamp: 1745832216, + receivedRewards: 134276125057404n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 24, + validatorIndex: '1062322', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 32, + validatorIndex: '1062768', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 273636n, + refSlot: 294399n, + frame: [8975, 9199], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9079475582843584, + receivedShares: 215145123566758n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745659800, + endTimestamp: 1745745816, + receivedRewards: 218367811572947n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 266871n, + refSlot: 287199n, + frame: [8750, 8974], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9147153970331007, + receivedShares: 161335072933603n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745573400, + endTimestamp: 1745659416, + receivedRewards: 163751732888061n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 260020n, + refSlot: 279999n, + frame: [8525, 8749], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9177574075447873, + receivedShares: 159335616377482n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745487000, + endTimestamp: 1745573016, + receivedRewards: 161722326200812n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 253151n, + refSlot: 272799n, + frame: [8300, 8524], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9050955136673701, + receivedShares: 154662344060746n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745400600, + endTimestamp: 1745486616, + receivedRewards: 156979052303770n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 246318n, + refSlot: 265599n, + frame: [8075, 8299], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9284329787823383, + receivedShares: 153124780085012n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745314200, + endTimestamp: 1745400216, + receivedRewards: 155418456948560n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 239378n, + refSlot: 258399n, + frame: [7850, 8074], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9329752884653509, + receivedShares: 138916480212291n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745227800, + endTimestamp: 1745313816, + receivedRewards: 140997329023643n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 232392n, + refSlot: 251199n, + frame: [7625, 7849], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9413300626756951, + receivedShares: 145296523158163n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745141400, + endTimestamp: 1745227416, + receivedRewards: 147472939498724n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 225341n, + refSlot: 243999n, + frame: [7400, 7624], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9457798185225983, + receivedShares: 156063013848372n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1745055000, + endTimestamp: 1745141016, + receivedRewards: 158400702914249n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 218249n, + refSlot: 236799n, + frame: [7175, 7399], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9437046130054199, + receivedShares: 151937455425790n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1744968600, + endTimestamp: 1745054616, + receivedRewards: 154213347192119n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 211199n, + refSlot: 229599n, + frame: [6950, 7174], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9395515385071712, + receivedShares: 146146107906600n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1744882200, + endTimestamp: 1744968216, + receivedRewards: 148335250292416n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 204188n, + refSlot: 222399n, + frame: [6050, 6949], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9158246402368915, + receivedShares: 619459500789606n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1744536600, + endTimestamp: 1744881816, + receivedRewards: 628738468727241n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.9977777777777778, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.9977777777777778, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 35, + validatorIndex: '1062771', + performance: 0.9977777777777778, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 176739n, + refSlot: 193599n, + frame: [5600, 6049], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9141372599324479, + receivedShares: 467201816799821n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1744363800, + endTimestamp: 1744536216, + receivedRewards: 474200096224003n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 1, + validatorIndex: '1062299', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 6, + validatorIndex: '1062304', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 7, + validatorIndex: '1062305', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 9, + validatorIndex: '1062307', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 10, + validatorIndex: '1062308', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 12, + validatorIndex: '1062310', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 15, + validatorIndex: '1062313', + performance: 0.9990123456790123, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 20, + validatorIndex: '1062318', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 21, + validatorIndex: '1062319', + performance: 0.9990123456790123, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 22, + validatorIndex: '1062320', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 23, + validatorIndex: '1062321', + performance: 0.9990123456790123, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 26, + validatorIndex: '1062324', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.9990123456790123, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 31, + validatorIndex: '1062767', + performance: 0.9980246913580247, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 33, + validatorIndex: '1062769', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 37, + validatorIndex: '1062773', + performance: 0.9995061728395062, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 163063n, + refSlot: 179199n, + frame: [3575, 5599], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.88051577486505, + receivedShares: 2626719111952182n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1743586200, + endTimestamp: 1744363416, + receivedRewards: 2666065094038033n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 104721n, + refSlot: 114399n, + frame: [3350, 3574], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8647037450222799, + receivedShares: 413651787990531n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1743499800, + endTimestamp: 1743585816, + receivedRewards: 419847934265173n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 5, + validatorIndex: '1062303', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 30, + validatorIndex: '1062766', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 98220n, + refSlot: 107199n, + frame: [3125, 3349], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8657789559105445, + receivedShares: 433585241114584n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1743413400, + endTimestamp: 1743499416, + receivedRewards: 440079973289013n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 14, + validatorIndex: '1062312', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 19, + validatorIndex: '1062317', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 91698n, + refSlot: 99999n, + frame: [2900, 3124], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8182254435174211, + receivedShares: 422215975869459n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1743327000, + endTimestamp: 1743413016, + receivedRewards: 428540406276703n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 2, + validatorIndex: '1062300', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 13, + validatorIndex: '1062311', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 16, + validatorIndex: '1062314', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 29, + validatorIndex: '1062765', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 34, + validatorIndex: '1062770', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 85353n, + refSlot: 92799n, + frame: [2675, 2899], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8176981721262923, + receivedShares: 377516626019384n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1743240600, + endTimestamp: 1743326616, + receivedRewards: 383171498798464n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 28, + validatorIndex: '1062764', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 79092n, + refSlot: 85599n, + frame: [2450, 2674], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8804917347901333, + receivedShares: 384000142578860n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1743154200, + endTimestamp: 1743240216, + receivedRewards: 389752132832451n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 0, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 1, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 2, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 3, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 4, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 5, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 6, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 7, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 8, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 9, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 10, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 11, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 12, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 13, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 14, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 15, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 16, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 17, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 18, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 19, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 20, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 21, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 22, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 23, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 24, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 25, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 26, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 27, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 28, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 29, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 30, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 31, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 32, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 33, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 34, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 35, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 36, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 37, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 38, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 72465n, + refSlot: 78399n, + frame: [2225, 2449], + indexInReport: 39, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8726372417309936, + receivedShares: 1002168957696437n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1743067800, + endTimestamp: 1743153816, + receivedRewards: 1017180582531806n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 0, + validatorIndex: '1062293', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x90309db94ae68fdf982b84bc25714b5fa00eccbda2273d01ee819e0e339dffd416eb77980fe0b34381fe5b49e5782cd5', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 1, + validatorIndex: '1062294', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa764f56c3a9bf5c74be2f9c399228b85ce74bdaf01389341f2f5ec297f94609952e8f5d857eaa714b2509fbf426074bd', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 2, + validatorIndex: '1062295', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa474aa9ebbc84e6c713bd68405be02ca717eec4996e6102c1a9a79ac8004db8538b5a10439430228079240ec74d8afee', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 3, + validatorIndex: '1062296', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x80c0a5bbdd588fe51b13b40c9a41cb6dd37143ecccf762e049324763f9fd148f26e77acaba96ce51d6220b9db49f2160', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 4, + validatorIndex: '1062297', + performance: 0.9952380952380953, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8c4ed9ee4ae698ba963384ab5b4f1834d854999522b3b041a10b2f66b7ae399f1615ab90f5a304c30dd035502dc5fd83', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 5, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 6, + validatorIndex: '1062299', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 7, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 8, + validatorIndex: '1062301', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 9, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 10, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 11, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 12, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 13, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 14, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 15, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 16, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 17, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 18, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 19, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 20, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 21, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 22, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 23, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 24, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 25, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 26, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 27, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 28, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 29, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 30, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 31, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 32, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 33, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 34, + validatorIndex: '1062765', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 35, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 36, + validatorIndex: '1062767', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 37, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 38, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 39, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 40, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 41, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 42, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 43, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 65855n, + refSlot: 71199n, + frame: [2000, 2224], + indexInReport: 44, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9121596662423873, + receivedShares: 281231377990979n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1742981400, + endTimestamp: 1743067416, + receivedRewards: 285443980971656n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 0, + validatorIndex: '1062293', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x90309db94ae68fdf982b84bc25714b5fa00eccbda2273d01ee819e0e339dffd416eb77980fe0b34381fe5b49e5782cd5', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 1, + validatorIndex: '1062294', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa764f56c3a9bf5c74be2f9c399228b85ce74bdaf01389341f2f5ec297f94609952e8f5d857eaa714b2509fbf426074bd', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 2, + validatorIndex: '1062295', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa474aa9ebbc84e6c713bd68405be02ca717eec4996e6102c1a9a79ac8004db8538b5a10439430228079240ec74d8afee', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 3, + validatorIndex: '1062296', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x80c0a5bbdd588fe51b13b40c9a41cb6dd37143ecccf762e049324763f9fd148f26e77acaba96ce51d6220b9db49f2160', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 4, + validatorIndex: '1062297', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8c4ed9ee4ae698ba963384ab5b4f1834d854999522b3b041a10b2f66b7ae399f1615ab90f5a304c30dd035502dc5fd83', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 5, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 6, + validatorIndex: '1062299', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 7, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 8, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 9, + validatorIndex: '1062302', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 10, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 11, + validatorIndex: '1062304', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 12, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 13, + validatorIndex: '1062306', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 14, + validatorIndex: '1062307', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 15, + validatorIndex: '1062308', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 16, + validatorIndex: '1062309', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 17, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 18, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 19, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 20, + validatorIndex: '1062313', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 21, + validatorIndex: '1062314', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 22, + validatorIndex: '1062315', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 23, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 24, + validatorIndex: '1062317', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 25, + validatorIndex: '1062318', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 26, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 27, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 28, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 29, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 30, + validatorIndex: '1062323', + performance: 0.9911111111111112, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 31, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 32, + validatorIndex: '1062325', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 33, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 34, + validatorIndex: '1062765', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 35, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 36, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 37, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 38, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 39, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 40, + validatorIndex: '1062771', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 41, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 42, + validatorIndex: '1062773', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 43, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 58916n, + refSlot: 63999n, + frame: [1775, 1999], + indexInReport: 44, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8921619563206921, + receivedShares: 243744710170097n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1742895000, + endTimestamp: 1742981016, + receivedRewards: 247395795265657n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 0, + validatorIndex: '1062293', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x90309db94ae68fdf982b84bc25714b5fa00eccbda2273d01ee819e0e339dffd416eb77980fe0b34381fe5b49e5782cd5', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 1, + validatorIndex: '1062294', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa764f56c3a9bf5c74be2f9c399228b85ce74bdaf01389341f2f5ec297f94609952e8f5d857eaa714b2509fbf426074bd', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 2, + validatorIndex: '1062295', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa474aa9ebbc84e6c713bd68405be02ca717eec4996e6102c1a9a79ac8004db8538b5a10439430228079240ec74d8afee', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 3, + validatorIndex: '1062296', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x80c0a5bbdd588fe51b13b40c9a41cb6dd37143ecccf762e049324763f9fd148f26e77acaba96ce51d6220b9db49f2160', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 4, + validatorIndex: '1062297', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8c4ed9ee4ae698ba963384ab5b4f1834d854999522b3b041a10b2f66b7ae399f1615ab90f5a304c30dd035502dc5fd83', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 5, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 6, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 7, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 8, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 9, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 10, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 11, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 12, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 13, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 14, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 15, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 16, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 17, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 18, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 19, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 20, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 21, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 22, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 23, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 24, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 25, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 26, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 27, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 28, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 29, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 30, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 31, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 32, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 33, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 34, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 35, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 36, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 37, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 38, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 39, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 40, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 41, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 42, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 43, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 52183n, + refSlot: 56799n, + frame: [1550, 1774], + indexInReport: 44, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8278093667823463, + receivedShares: 114087624957861n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1742808600, + endTimestamp: 1742894616, + receivedRewards: 115796558976494n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 0, + validatorIndex: '1062293', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x90309db94ae68fdf982b84bc25714b5fa00eccbda2273d01ee819e0e339dffd416eb77980fe0b34381fe5b49e5782cd5', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 1, + validatorIndex: '1062294', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa764f56c3a9bf5c74be2f9c399228b85ce74bdaf01389341f2f5ec297f94609952e8f5d857eaa714b2509fbf426074bd', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 2, + validatorIndex: '1062295', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa474aa9ebbc84e6c713bd68405be02ca717eec4996e6102c1a9a79ac8004db8538b5a10439430228079240ec74d8afee', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 3, + validatorIndex: '1062296', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x80c0a5bbdd588fe51b13b40c9a41cb6dd37143ecccf762e049324763f9fd148f26e77acaba96ce51d6220b9db49f2160', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 4, + validatorIndex: '1062297', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8c4ed9ee4ae698ba963384ab5b4f1834d854999522b3b041a10b2f66b7ae399f1615ab90f5a304c30dd035502dc5fd83', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 5, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 6, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 7, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 8, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 9, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 10, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 11, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 12, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 13, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 14, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 15, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 16, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 17, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 18, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 19, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 20, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 21, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 22, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 23, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 24, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 25, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 26, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 27, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 28, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 29, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 30, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 31, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 32, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 33, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 34, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 35, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 36, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 37, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 38, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 39, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 40, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 41, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 42, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 43, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 45916n, + refSlot: 49599n, + frame: [1325, 1549], + indexInReport: 44, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9128529392040997, + receivedShares: 113619984591029n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1742722200, + endTimestamp: 1742808216, + receivedRewards: 115321913761137n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 0, + validatorIndex: '1062293', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x90309db94ae68fdf982b84bc25714b5fa00eccbda2273d01ee819e0e339dffd416eb77980fe0b34381fe5b49e5782cd5', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 1, + validatorIndex: '1062294', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa764f56c3a9bf5c74be2f9c399228b85ce74bdaf01389341f2f5ec297f94609952e8f5d857eaa714b2509fbf426074bd', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 2, + validatorIndex: '1062295', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa474aa9ebbc84e6c713bd68405be02ca717eec4996e6102c1a9a79ac8004db8538b5a10439430228079240ec74d8afee', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 3, + validatorIndex: '1062296', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x80c0a5bbdd588fe51b13b40c9a41cb6dd37143ecccf762e049324763f9fd148f26e77acaba96ce51d6220b9db49f2160', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 4, + validatorIndex: '1062297', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8c4ed9ee4ae698ba963384ab5b4f1834d854999522b3b041a10b2f66b7ae399f1615ab90f5a304c30dd035502dc5fd83', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 5, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 6, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 7, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 8, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 9, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 10, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 11, + validatorIndex: '1062304', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 12, + validatorIndex: '1062305', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 13, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 14, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 15, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 16, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 17, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 18, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 19, + validatorIndex: '1062312', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 20, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 21, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 22, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 23, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 24, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 25, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 26, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 27, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 28, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 29, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 30, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 31, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 32, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 33, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 34, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 35, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 36, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 37, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 38, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 39, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 40, + validatorIndex: '1062771', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 41, + validatorIndex: '1062772', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 42, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 43, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 39008n, + refSlot: 42399n, + frame: [1100, 1324], + indexInReport: 44, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.9160215424655266, + receivedShares: 76889885807893n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1742635800, + endTimestamp: 1742721816, + receivedRewards: 78041629843185n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 0, + validatorIndex: '1062293', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x90309db94ae68fdf982b84bc25714b5fa00eccbda2273d01ee819e0e339dffd416eb77980fe0b34381fe5b49e5782cd5', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 1, + validatorIndex: '1062294', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa764f56c3a9bf5c74be2f9c399228b85ce74bdaf01389341f2f5ec297f94609952e8f5d857eaa714b2509fbf426074bd', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 2, + validatorIndex: '1062295', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa474aa9ebbc84e6c713bd68405be02ca717eec4996e6102c1a9a79ac8004db8538b5a10439430228079240ec74d8afee', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 3, + validatorIndex: '1062296', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x80c0a5bbdd588fe51b13b40c9a41cb6dd37143ecccf762e049324763f9fd148f26e77acaba96ce51d6220b9db49f2160', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 4, + validatorIndex: '1062297', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8c4ed9ee4ae698ba963384ab5b4f1834d854999522b3b041a10b2f66b7ae399f1615ab90f5a304c30dd035502dc5fd83', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 5, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 6, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 7, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 8, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 9, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 10, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 11, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 12, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 13, + validatorIndex: '1062306', + performance: 0.9955555555555555, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 14, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 15, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 16, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 17, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 18, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 19, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 20, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 21, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 22, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 23, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 24, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 25, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 26, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 27, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 28, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 29, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 30, + validatorIndex: '1062323', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 31, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 32, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 33, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 34, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 35, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 36, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 37, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 38, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 39, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 40, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 41, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 42, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 43, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 32087n, + refSlot: 35199n, + frame: [875, 1099], + indexInReport: 44, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8988961100131287, + receivedShares: 68356588564998n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1742549400, + endTimestamp: 1742635416, + receivedRewards: 69380511182719n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 0, + validatorIndex: '1062288', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa06926875bcd285e4d6cf2477ae78dc962303f4f4a70c374892f21ad7895cfc2f3986293cbf16d2b98f4b21050f6d6ab', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 1, + validatorIndex: '1062289', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb53e9b5cb95e32e9242f9ba37d8769eaaf6f67d97c9a2a17fd3f39b8b9f75564f178e7a0d392ee94521fa6330049512b', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 2, + validatorIndex: '1062290', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa10d59907e08e09f6bc3d241bedcc0565102ad3c391dd91bb6b4c8c7fbe922156060c14198520b9b20f16ff4783dc5dd', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 3, + validatorIndex: '1062291', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa22dcedbc60859f72e9f7d9211d67bc150ec9b06153ce342f87799b8fd29538c6e95f1c574c9fa2fb629843079ddc41', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 4, + validatorIndex: '1062292', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb2c1346b591bb88f0f3f1bd78ac24e4a28d0d3b4fa116611692da7b41361236b798014ffb911d983828bdcffdbc0cbaf', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 5, + validatorIndex: '1062293', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x90309db94ae68fdf982b84bc25714b5fa00eccbda2273d01ee819e0e339dffd416eb77980fe0b34381fe5b49e5782cd5', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 6, + validatorIndex: '1062294', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa764f56c3a9bf5c74be2f9c399228b85ce74bdaf01389341f2f5ec297f94609952e8f5d857eaa714b2509fbf426074bd', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 7, + validatorIndex: '1062295', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa474aa9ebbc84e6c713bd68405be02ca717eec4996e6102c1a9a79ac8004db8538b5a10439430228079240ec74d8afee', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 8, + validatorIndex: '1062296', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x80c0a5bbdd588fe51b13b40c9a41cb6dd37143ecccf762e049324763f9fd148f26e77acaba96ce51d6220b9db49f2160', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 9, + validatorIndex: '1062297', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8c4ed9ee4ae698ba963384ab5b4f1834d854999522b3b041a10b2f66b7ae399f1615ab90f5a304c30dd035502dc5fd83', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 10, + validatorIndex: '1062298', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x816e44c8db28a716f1aec8e81eb50f8740b9e2812871e66ad971db61e3d35c8b1170b78b470a42453f2f135393bbc0bb', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 11, + validatorIndex: '1062299', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8b68d9b25f66a6fcfdf7f7c0b29d357c9714cd1af18f186c75e219e6dfed5ce491b5345e645c45716ff0b23031e1bc11', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 12, + validatorIndex: '1062300', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb22cd107f040c1a82e4e3fd83963798e08c49a002c566b2a4f3bb4ed69d3b8baa458339fa3d7b50c5716d51c6e414396', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 13, + validatorIndex: '1062301', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa2efaf6d0c34a8ecf1367ceebd3c265b1492120c17dd9bc0b8937edda68bfada3c6b1af42d29c1a26d56f5845eb42551', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 14, + validatorIndex: '1062302', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb9035494702ff161308857dd8a09724611d62b401e148adbac53ce82b9204682a92aeaf0b1529485abde4352ab1ac3a0', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 15, + validatorIndex: '1062303', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8738b092aa0b9990d0f401b390c6e01a9b9a9d55d51e435851e21b90a873ea1ac83e10d25644291df7a1ff0f62baf791', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 16, + validatorIndex: '1062304', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb8f74a31fc1cd3017f6fd38b36113a717119209ede645ee2ab5a025c3c69bf1c56b857ca907395f9972df3d4ea7c6845', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 17, + validatorIndex: '1062305', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95e394279543e6706321259e003a7a68cd33103f0c6854147e49d5ed7717f535abc53003cd9ff98a5790012655788b24', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 18, + validatorIndex: '1062306', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91f11fd5e0f9d6ec1a252cab5bf19f09121a66524d8f28773de0eb93f4c592f7ee146752217b7a6ab96d70115195f4c3', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 19, + validatorIndex: '1062307', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8ed60e4610dbc350eb91543f66e174cf64a6c8232762de7ac473a1effa6bd8089309aba7dc41a8c463af126ee34f6819', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 20, + validatorIndex: '1062308', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaad4773322e9ba50becd34117fee300bdda026bb28c0631508f5ae2299b79eb49070332ad9ea6b71d953f1e5a0662ecf', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 21, + validatorIndex: '1062309', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa6730611e8e28429dd03082bd390d4a6b412a520ef3a0e937eaa2b7ce29e8e45da5f96c502f684af2ca31632984004af', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 22, + validatorIndex: '1062310', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8f3e6876031aff1e6d0534e75d5bc37aab658536d00138fb2433419117019a9c9bab60a768411b8091d59d8df4b636f0', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 23, + validatorIndex: '1062311', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x8eaf96a332ba91e2dd57840b3078bb4865f854bc4c352d86b21e353f604d9767c02230bcc24ac00448c63430e42143de', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 24, + validatorIndex: '1062312', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xafab349fec3f4ca5931a834ca9e2bd9c0cca68febe94d38066969cf5a59be3094659a9644f6b0a4389f656c9c356828e', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 25, + validatorIndex: '1062313', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xae116ebfce4fc7d160c83a9db3eb4a85eabc66fb51c945be7c9d777a0674f8687411fe56aa4ff6d64274fb95618b4ad7', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 26, + validatorIndex: '1062314', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb173f80e8bdcb333ae8877f19b146b8623df114f0ba78f269f38094b1cd2417c7ff2c3dbde8fe9bfb6e913452316497f', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 27, + validatorIndex: '1062315', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb3068d96de398d1b7ec0be2aaf5e8669c059b0ba071ddbcb06e7d2d62f7e4d378cbd9357f16f6276410118fc36524031', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 28, + validatorIndex: '1062316', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb7ec271df38e3bda9357483f26d2f04dcc468e4986be39ce378725223d94ba032474eb340addada435d3aa75736d092a', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 29, + validatorIndex: '1062317', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x89624374831f8d80dbc1cea6499c3ea56c63811001d93ac70da283da7d35ed04ab1a64ab423c46e72e2855dd1dfaa98e', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 30, + validatorIndex: '1062318', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x812a5c628eab51bfb16a470bb2e3724496d7a8c66987e390ef82d5844e415114297c91d27919b7e7e3a947850a6afa45', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 31, + validatorIndex: '1062319', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xacc4ce9cb0bd8146bb8f2d05c810353b140106fa348613c73b17371c62d0f678a34ab0444b9819a7e815c969c7d3fac4', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 32, + validatorIndex: '1062320', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8ac6721cbfbd1fa99a5667fbd2c01c04e222f9b665e50e27719a62758b483f35d9172f0a23c85b2cd039c7c60fd8a05', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 33, + validatorIndex: '1062321', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x86512312bbaac904709b212dceb8857cb3d9ec3a1c6c18b5935e85cdb5f07cf75c2fb3b71372bf924ea3e7abebf2ac99', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 34, + validatorIndex: '1062322', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95a030dde245b814f253276dae716358c900fadc68c12a8b2303e82f5aebea22d27743c33c71c25cbffd2b535317583a', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 35, + validatorIndex: '1062323', + performance: 0.9975062344139651, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x87b5ca34e3ccabf9ceafed26a8d87328151439db2a8aacbc1d2c9b6259843360c14a6f4ad51792e5164c2aad332ef432', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 36, + validatorIndex: '1062324', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaffca34aed22bd79a02d867405bb122c1d501a1a612117a512e821049f0c0554fd5bb38e046653b338a2eb382475cb01', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 37, + validatorIndex: '1062325', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa8014aba231312a685a4ff322ea1a45e196ef4049d29f77649dcddcd68b862fa4131891fd55b8021786c04ebc9a9099c', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 38, + validatorIndex: '1062764', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa7e858c84f5d54ad41fb1f6f823b3813f5d1dc6ae8134abd4f322ae901c1f457301b11e746adaf6fe9eabeb65aec51ae', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 39, + validatorIndex: '1062765', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa4f2628f5363836a7cb4442e5e4909205754b9c7c25197c2248bd8a751fccd0b2500e56b97fcb57f2a8db1771d9a6164', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 40, + validatorIndex: '1062766', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x91e45339877dc96aac0efafe245085cb91fff976f1a3cc8963dd44f75d64753897ba50e757e16e18ac28b82ab0a6ef36', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 41, + validatorIndex: '1062767', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xaa84f2c0fa2ec769201de7f46909da50e4c8e77daff13d916c1af5d7e95ee1c1e88ff53d53e545e17ca5ddf75c293fb0', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 42, + validatorIndex: '1062768', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xb10179d58744507fed63646d7b8e60e5333251d590ce8ca3b647f95dbd33c319852e0bfe5bce8d526020365b4fde0f2e', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 43, + validatorIndex: '1062769', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84ddb10140e7fd7104ff30ba7c0708da86fb347111701aad48425768975c50a2793a691a5b46024e9286b4d66d0a69a0', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 44, + validatorIndex: '1062770', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x84549fd235c39cc45ced8d5a9c0482263db29bf9f624fec93e35081f5f0d52acc299fbf088118a5f211094f4e73fb211', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 45, + validatorIndex: '1062771', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xa50a81b60599b46cdf9653370d0f5d36dc1706730d5fef934c5ab210eba56eb67b831dffc1216d8fa65b1998e697949b', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 46, + validatorIndex: '1062772', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0xac1b7877f5c711fb9350c9cbddf66edfc4e4b6856f0fd2d9f43b59728a8069d82544c72e659f61c8328d5a70e7ec345c', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 47, + validatorIndex: '1062773', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x95f60bce8be3134d5aef93b15a07a7746e822dcacbb26e99be23810c41bcbca090e211d887eef2f67c8fb00b5bd93dc5', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 48, + validatorIndex: '1062774', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x945810ca58f020148e37511d85b93f99af3ffd01f70372bcb4c603aeb75945363e628eca68873a764042a5fc49da12d2', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, + { + blockNumber: 25299n, + refSlot: 27999n, + frame: [200, 874], + indexInReport: 49, + validatorIndex: '1062775', + performance: 1, + slashed: false, + threshold: 0.8632094438723824, + receivedShares: 144810577428744n, + rewardShare: 1, + fee: 600n, + pubkey: + '0x9084299ebfa9fe19d98ab6469735a5053d064537ca4c984910fe1a31847d094ccd4bbd7d0cd023c3b18915695996ef60', + startTimestamp: 1742290200, + endTimestamp: 1742549016, + receivedRewards: 146979714722270n, + }, +]; diff --git a/mock/rewards/mock-data.ts b/mock/rewards/mock-data.ts new file mode 100644 index 000000000..526890622 --- /dev/null +++ b/mock/rewards/mock-data.ts @@ -0,0 +1,12 @@ +import { OperatorRewardsHistory } from '@lidofinance/lido-csm-sdk'; + +export type MockScenarioData = { + nodeOperatorId: number; + rewardsHistory: OperatorRewardsHistory; +}; + +export const createMockRewardsHistory = ( + data: OperatorRewardsHistory, +): OperatorRewardsHistory => { + return data; +}; diff --git a/mock/rewards/mock-providers.tsx b/mock/rewards/mock-providers.tsx new file mode 100644 index 000000000..de7bbf40f --- /dev/null +++ b/mock/rewards/mock-providers.tsx @@ -0,0 +1,53 @@ +import { FC, PropsWithChildren } from 'react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { createMockRewardsHistory, type MockScenarioData } from './mock-data'; +import { + NodeOperatorContext, + NodeOperatorContextValue, +} from 'modules/web3/operator-provider/node-operator-provider'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import { KEY_OPERATOR_REWARDS_HISTORY } from 'modules/web3'; +import { hashKey } from 'utils'; + +export const MockRewardsHistoryProvider: FC< + PropsWithChildren<{ scenario: MockScenarioData }> +> = ({ children, scenario }) => { + const mockRewardsHistory = createMockRewardsHistory(scenario.rewardsHistory); + + // Create a unique QueryClient for this scenario to avoid cache conflicts + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + queryKeyHashFn: hashKey, + retry: false, + ...STRATEGY_IMMUTABLE, + }, + }, + }); + + // Pre-populate the query cache with mock data + queryClient.setQueryData( + [ + ...KEY_OPERATOR_REWARDS_HISTORY, + { nodeOperatorId: BigInt(scenario.nodeOperatorId) }, + ], + mockRewardsHistory, + ); + + // Mock node operator context value + const mockNodeOperatorContextValue: NodeOperatorContextValue = { + isPending: false, + nodeOperator: { + id: BigInt(scenario.nodeOperatorId), + } as any, + switchNodeOperator: () => {}, + }; + + return ( + + + {children} + + + ); +}; diff --git a/mock/rewards/test-scenarios.ts b/mock/rewards/test-scenarios.ts new file mode 100644 index 000000000..fb3d5e5f0 --- /dev/null +++ b/mock/rewards/test-scenarios.ts @@ -0,0 +1,88 @@ +import { MockScenarioData } from './mock-data'; +import { data as _data } from './data'; +import { OperatorRewardsHistory } from '@lidofinance/lido-csm-sdk'; + +const data = _data as OperatorRewardsHistory; + +export type TestScenario = { + title: string; + description: string; + data: MockScenarioData; +}; + +export const testScenarios: TestScenario[] = [ + { + title: 'Full Dataset', + description: 'All rewards history data from mock', + data: { + nodeOperatorId: 1, + rewardsHistory: data, + }, + }, + { + title: 'Small Dataset (First 10)', + description: 'Limited view with first 10 reward records', + data: { + nodeOperatorId: 1, + rewardsHistory: data.slice(0, 10), + }, + }, + { + title: 'Medium Dataset (First 50)', + description: 'Medium-sized dataset with 50 reward records', + data: { + nodeOperatorId: 1, + rewardsHistory: data.slice(0, 50), + }, + }, + { + title: 'High Performance Only', + description: 'Only validators with performance >= 0.99', + data: { + nodeOperatorId: 1, + rewardsHistory: data.filter((record) => record.performance >= 0.99), + }, + }, + { + title: 'Below Threshold Performance', + description: 'Validators performing below threshold', + data: { + nodeOperatorId: 1, + rewardsHistory: data.filter( + (record) => record.performance < record.threshold, + ), + }, + }, + { + title: 'Single Validator', + description: 'Single validator view', + data: { + nodeOperatorId: 1, + rewardsHistory: data.slice(0, 1), + }, + }, + { + title: 'Empty State', + description: 'No rewards history - empty state', + data: { + nodeOperatorId: 1, + rewardsHistory: [], + }, + }, + { + title: 'Earliest Rewards (Last 20)', + description: 'Most earliest reward records', + data: { + nodeOperatorId: 1, + rewardsHistory: data.slice(-20), + }, + }, + { + title: 'Single Pubkey Filter', + description: 'All records for a single validator pubkey', + data: { + nodeOperatorId: 1, + rewardsHistory: data.filter((record) => record.pubkey === data[0].pubkey), + }, + }, +]; diff --git a/mock/wrapped/mock-data.ts b/mock/wrapped/mock-data.ts new file mode 100644 index 000000000..79947842c --- /dev/null +++ b/mock/wrapped/mock-data.ts @@ -0,0 +1,12 @@ +import { WrappedStatsRaw } from 'features/wrapped/data/types'; + +export type MockWrappedScenarioData = { + nodeOperatorId: number; + stats: WrappedStatsRaw; +}; + +export const createMockWrappedStats = ( + data: WrappedStatsRaw, +): WrappedStatsRaw => { + return data; +}; diff --git a/modules/siwe/index.ts b/modules/siwe/index.ts new file mode 100644 index 000000000..d9f991778 --- /dev/null +++ b/modules/siwe/index.ts @@ -0,0 +1,10 @@ +export { SiweAuthProvider } from './siwe-auth-provider'; +export { SiweAuthGate } from './siwe-auth-gate'; +export { useSiweAuth } from './use-siwe-auth'; +export type { + SiweAuthContextType, + SiweNonceResponse, + SiweOptions, + SiweSigninPayload, + SiweSigninResponse, +} from './types'; diff --git a/modules/siwe/siwe-auth-context.ts b/modules/siwe/siwe-auth-context.ts new file mode 100644 index 000000000..b71cb3cdc --- /dev/null +++ b/modules/siwe/siwe-auth-context.ts @@ -0,0 +1,4 @@ +import { createContext } from 'react'; +import type { SiweAuthContextType } from './types'; + +export const SiweAuthContext = createContext(null); diff --git a/modules/siwe/siwe-auth-gate.tsx b/modules/siwe/siwe-auth-gate.tsx new file mode 100644 index 000000000..bd1ff9732 --- /dev/null +++ b/modules/siwe/siwe-auth-gate.tsx @@ -0,0 +1,14 @@ +import { FC, PropsWithChildren, ReactNode } from 'react'; +import { useSiweAuth } from './use-siwe-auth'; + +type SiweAuthGateProps = { + fallback?: ReactNode; +}; + +export const SiweAuthGate: FC> = ({ + fallback, + children, +}) => { + const { token } = useSiweAuth(); + return <>{token ? children : fallback}; +}; diff --git a/modules/siwe/siwe-auth-provider.tsx b/modules/siwe/siwe-auth-provider.tsx new file mode 100644 index 000000000..b41da5fc3 --- /dev/null +++ b/modules/siwe/siwe-auth-provider.tsx @@ -0,0 +1,98 @@ +import { useDappStatus } from 'modules/web3'; +import { useAddressValidation } from 'providers/address-validation-provider'; +import { useModalActions } from 'providers/modal-provider'; +import { FC, PropsWithChildren, useCallback, useMemo } from 'react'; +import { useSessionStorage } from 'shared/hooks'; +import { trackMatomoSiweEvent } from 'utils/track-matomo-event'; +import { SiweAuthContext } from './siwe-auth-context'; +import { useModalStages } from './use-modal-stages'; +import { useSiwe } from './use-siwe'; +import type { + SiweNonceResponse, + SiweSigninPayload, + SiweSigninResponse, +} from './types'; + +const SIWE_STATEMENT = + 'The section you are attempting to access requires you to prove the address ownership.'; + +type SiweAuthProviderProps = { + signin: (payload: SiweSigninPayload) => Promise; + getNonce: () => Promise; +}; + +export const SiweAuthProvider: FC> = ({ + signin, + getNonce, + children, +}) => { + const { address } = useDappStatus(); + const siwe = useSiwe({ statement: SIWE_STATEMENT }); + const [token, setToken] = useSessionStorage( + `siwe-token-${address}`, + undefined, + ); + + const { txModalStages: modalStages } = useModalStages(); + const { closeModal } = useModalActions(); + const { validateAddress } = useAddressValidation(); + + const signIn = useCallback(async () => { + trackMatomoSiweEvent(); + + const result = await validateAddress(address); + if (!result) return; + + modalStages.sign(); + + // The backend rejects any SIWE nonce it did not issue, and the nonce is + // short-lived (TTL-bound), so fetch a fresh one right before signing. + let nonce: string; + try { + ({ nonce } = await getNonce()); + } catch (err) { + modalStages.failed((err as Error).message); + return; + } + + try { + const payload = await siwe(nonce); + + modalStages.pending(); + try { + const data = await signin(payload); + setToken(`${data.token_type} ${data.access_token}`); + trackMatomoSiweEvent('success'); + closeModal(); + } catch (err) { + modalStages.failed((err as Error).message); + } + } catch (_e) { + modalStages.rejected(); + } + }, [ + address, + closeModal, + getNonce, + modalStages, + setToken, + signin, + siwe, + validateAddress, + ]); + + const logout = useCallback(() => { + setToken(undefined); + }, [setToken]); + + const value = useMemo( + () => ({ token, signIn, logout }), + [logout, signIn, token], + ); + + return ( + + {children} + + ); +}; diff --git a/modules/siwe/types.ts b/modules/siwe/types.ts new file mode 100644 index 000000000..5612dde24 --- /dev/null +++ b/modules/siwe/types.ts @@ -0,0 +1,23 @@ +export type SiweOptions = { + statement: string; +}; + +export type SiweSigninPayload = { + message: string; + signature: string; +}; + +export type SiweNonceResponse = { + nonce: string; +}; + +export type SiweSigninResponse = { + access_token: string; + token_type: string; +}; + +export type SiweAuthContextType = { + token?: string; + signIn: () => Promise; + logout: () => void; +}; diff --git a/modules/siwe/use-modal-stages.tsx b/modules/siwe/use-modal-stages.tsx new file mode 100644 index 000000000..52f8cf6e7 --- /dev/null +++ b/modules/siwe/use-modal-stages.tsx @@ -0,0 +1,36 @@ +import { + TransactionModalTransitStage, + TxStageFail, + TxStagePending, + TxStagePermit, + useTransactionModalStage, +} from 'shared/transaction-modal'; +import { ErrorCode, extractErrorMessage, getErrorCode } from 'utils'; + +const getModalStages = (transitStage: TransactionModalTransitStage) => ({ + sign: () => transitStage(), + + pending: () => + transitStage( + , + ), + + failed: (error: unknown) => + transitStage( + , + ), + + rejected: () => + transitStage( + , + ), +}); + +export const useModalStages = () => useTransactionModalStage(getModalStages); diff --git a/modules/siwe/use-siwe-auth.ts b/modules/siwe/use-siwe-auth.ts new file mode 100644 index 000000000..0fd3cc75b --- /dev/null +++ b/modules/siwe/use-siwe-auth.ts @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import invariant from 'tiny-invariant'; +import { SiweAuthContext } from './siwe-auth-context'; + +export const useSiweAuth = () => { + const context = useContext(SiweAuthContext); + invariant( + context, + 'Attempt to use `useSiweAuth` outside of `SiweAuthProvider`', + ); + return context; +}; diff --git a/modules/siwe/use-siwe.ts b/modules/siwe/use-siwe.ts new file mode 100644 index 000000000..275fbd288 --- /dev/null +++ b/modules/siwe/use-siwe.ts @@ -0,0 +1,49 @@ +import { addDays } from 'date-fns'; +import { useDappStatus } from 'modules/web3'; +import { useCallback } from 'react'; +import { SiweMessage } from 'siwe'; +import invariant from 'tiny-invariant'; +import { useSignMessage } from 'wagmi'; +import type { SiweOptions } from './types'; + +const createSiweMessage = ( + address: string, + statement: string, + nonce: string, + chainId?: number, +) => { + const scheme = window.location.protocol.slice(0, -1); + const domain = window.location.host; + const uri = window.location.origin; + + const message = new SiweMessage({ + scheme, + domain, + address, + statement, + uri, + version: '1', + chainId, + nonce, + expirationTime: addDays(new Date(), 1).toISOString(), + }); + return message.prepareMessage(); +}; + +export const useSiwe = ({ statement }: SiweOptions) => { + const { address, chainId } = useDappStatus(); + const { mutateAsync: signMessageAsync } = useSignMessage(); + + return useCallback( + async (nonce: string) => { + invariant(address, 'Signer is not available'); + + const message = createSiweMessage(address, statement, nonce, chainId); + const signature = await signMessageAsync({ + message, + }); + return { signature, message }; + }, + [address, chainId, signMessageAsync, statement], + ); +}; diff --git a/modules/surveys-sdk/api/__tests__/endpoints.test.ts b/modules/surveys-sdk/api/__tests__/endpoints.test.ts new file mode 100644 index 000000000..c5a90909f --- /dev/null +++ b/modules/surveys-sdk/api/__tests__/endpoints.test.ts @@ -0,0 +1,91 @@ +import { appendQuery, joinUrl, operatorKey, parseOperatorKey } from '../url'; + +// Inline MODULE_NAME values to avoid pulling the full csm-sdk into the jest +// environment (which transitively resolves lido-ethereum-sdk ipfs deps). +// Keep these in sync with `@lidofinance/lido-csm-sdk`'s MODULE_NAME enum. +const CSM = 'CSM' as never; +const CM = 'CM' as never; + +describe('operatorKey', () => { + it('produces lowercase prefix with bigint', () => { + expect(operatorKey(CSM, 42n)).toBe('csm-42'); + }); + + it('produces lowercase prefix with bigint 0', () => { + expect(operatorKey(CSM, 0n)).toBe('csm-0'); + }); + + it('returns undefined when id is undefined', () => { + expect(operatorKey(CSM, undefined)).toBeUndefined(); + }); + + it('handles future cm prefix', () => { + expect(operatorKey(CM, 5n)).toBe('cm-5'); + }); +}); + +describe('parseOperatorKey', () => { + it('accepts well-formed csm key', () => { + expect(parseOperatorKey('csm-42')).toBe('csm-42'); + }); + + it('accepts well-formed cm key', () => { + expect(parseOperatorKey('cm-7')).toBe('cm-7'); + }); + + it('rejects uppercase prefix', () => { + expect(parseOperatorKey('CSM-42')).toBeNull(); + }); + + it('rejects missing id', () => { + expect(parseOperatorKey('csm-')).toBeNull(); + }); + + it('rejects unknown module', () => { + expect(parseOperatorKey('xyz-1')).toBeNull(); + }); +}); + +describe('joinUrl', () => { + it('joins base and path with single slash', () => { + expect(joinUrl('https://api.example.com', 'foo')).toBe( + 'https://api.example.com/foo', + ); + }); + + it('strips trailing slash from base', () => { + expect(joinUrl('https://api.example.com/', 'foo')).toBe( + 'https://api.example.com/foo', + ); + }); + + it('strips leading slash from path', () => { + expect(joinUrl('https://api.example.com', '/foo')).toBe( + 'https://api.example.com/foo', + ); + }); + + it('strips both leading and trailing slashes', () => { + expect(joinUrl('https://api.example.com/', '/foo/bar')).toBe( + 'https://api.example.com/foo/bar', + ); + }); +}); + +describe('appendQuery', () => { + it('returns url unchanged when no query', () => { + expect(appendQuery('https://x.test/a')).toBe('https://x.test/a'); + }); + + it('appends single param', () => { + expect(appendQuery('https://x.test/a', { k: 'v' })).toBe( + 'https://x.test/a?k=v', + ); + }); + + it('skips undefined values', () => { + expect(appendQuery('https://x.test/a', { a: '1', b: undefined })).toBe( + 'https://x.test/a?a=1', + ); + }); +}); diff --git a/modules/surveys-sdk/api/__tests__/surveys-api.test.ts b/modules/surveys-sdk/api/__tests__/surveys-api.test.ts new file mode 100644 index 000000000..15fbe33c6 --- /dev/null +++ b/modules/surveys-sdk/api/__tests__/surveys-api.test.ts @@ -0,0 +1,202 @@ +jest.mock('config', () => ({ + config: { surveysApiUrl: 'https://surveys.test' }, +})); + +jest.mock('consts/external-links', () => ({ + getExternalLinks: () => ({ surveyApi: 'https://default.test' }), +})); + +import { FetcherError } from 'utils/fetcher-error'; +import { + isSurveysApiConfigured, + SURVEYS_API_BASE_URL, + surveysDelete, + surveysGet, + surveysGetNonce, + surveysPost, + surveysSignin, +} from '../surveys-api'; +import { SurveysApiError, isAuthError } from '../errors'; + +const mockFetch = (status: number, body?: unknown): jest.Mock => { + const json = jest.fn().mockResolvedValue(body ?? { ok: true }); + return jest.fn().mockResolvedValue({ + ok: status >= 200 && status < 300, + status, + headers: { get: () => null }, + json, + }); +}; + +const lastFetchInit = (fetchMock: jest.Mock): RequestInit => + fetchMock.mock.calls[fetchMock.mock.calls.length - 1][1] as RequestInit; + +const lastFetchUrl = (fetchMock: jest.Mock): string => + fetchMock.mock.calls[fetchMock.mock.calls.length - 1][0] as string; + +describe('surveys-api', () => { + beforeEach(() => { + (global as unknown as { fetch: jest.Mock }).fetch = mockFetch(200, { + hello: 'world', + }); + }); + + it('resolves base URL from config at module load', () => { + expect(SURVEYS_API_BASE_URL).toBe('https://surveys.test'); + expect(isSurveysApiConfigured).toBe(true); + }); + + it('sets Authorization header when token is provided', async () => { + const fetchMock = (global as unknown as { fetch: jest.Mock }).fetch; + await surveysGet('csm-1/contacts', { token: 'Bearer xyz' }); + + const init = lastFetchInit(fetchMock); + expect((init.headers as Record).Authorization).toBe( + 'Bearer xyz', + ); + }); + + it('omits Authorization header when no token', async () => { + const fetchMock = (global as unknown as { fetch: jest.Mock }).fetch; + await surveysGet('open/csm-1'); + + const init = lastFetchInit(fetchMock); + expect( + (init.headers as Record).Authorization, + ).toBeUndefined(); + }); + + it('builds the full URL by joining base + path', async () => { + const fetchMock = (global as unknown as { fetch: jest.Mock }).fetch; + await surveysGet('csm-1/contacts'); + + expect(lastFetchUrl(fetchMock)).toBe('https://surveys.test/csm-1/contacts'); + }); + + it('appends query params', async () => { + const fetchMock = (global as unknown as { fetch: jest.Mock }).fetch; + await surveysGet('csm-1/contacts', { + query: { foo: 'bar', skip: undefined }, + }); + + expect(lastFetchUrl(fetchMock)).toBe( + 'https://surveys.test/csm-1/contacts?foo=bar', + ); + }); + + it('surveysPost sends a JSON-serialized body', async () => { + const fetchMock = (global as unknown as { fetch: jest.Mock }).fetch; + await surveysPost('csm-1/x', { a: 1 }); + + const init = lastFetchInit(fetchMock); + expect(init.method).toBe('POST'); + expect(init.body).toBe(JSON.stringify({ a: 1 })); + }); + + it('surveysDelete issues a DELETE', async () => { + const fetchMock = (global as unknown as { fetch: jest.Mock }).fetch; + await surveysDelete('csm-1/x', { token: 'tok' }); + + expect(lastFetchInit(fetchMock).method).toBe('DELETE'); + }); + + it('surveysSignin posts to /auth/signin without a token', async () => { + (global as unknown as { fetch: jest.Mock }).fetch = mockFetch(200, { + access_token: 'a', + token_type: 'Bearer', + }); + + const res = await surveysSignin({ message: 'm', signature: 's' }); + expect(res.access_token).toBe('a'); + + const fetchMock = (global as unknown as { fetch: jest.Mock }).fetch; + expect(lastFetchUrl(fetchMock)).toBe('https://surveys.test/auth/signin'); + expect( + (lastFetchInit(fetchMock).headers as Record) + .Authorization, + ).toBeUndefined(); + }); + + it('surveysGetNonce GETs /auth/nonce without a token', async () => { + (global as unknown as { fetch: jest.Mock }).fetch = mockFetch(200, { + nonce: 'server-nonce', + }); + + const res = await surveysGetNonce(); + expect(res.nonce).toBe('server-nonce'); + + const fetchMock = (global as unknown as { fetch: jest.Mock }).fetch; + expect(lastFetchUrl(fetchMock)).toBe('https://surveys.test/auth/nonce'); + expect(lastFetchInit(fetchMock).method).toBe('GET'); + expect( + (lastFetchInit(fetchMock).headers as Record) + .Authorization, + ).toBeUndefined(); + }); + + it('invokes onAuthError on 401 then throws SurveysApiError', async () => { + (global as unknown as { fetch: jest.Mock }).fetch = mockFetch(401, { + message: 'unauthorized', + }); + const onAuthError = jest.fn(); + + await expect( + surveysGet('me', { token: 'tok', onAuthError }), + ).rejects.toBeInstanceOf(SurveysApiError); + expect(onAuthError).toHaveBeenCalledTimes(1); + }); + + it('invokes onAuthError on 403', async () => { + (global as unknown as { fetch: jest.Mock }).fetch = mockFetch(403, {}); + const onAuthError = jest.fn(); + + await expect( + surveysGet('me', { token: 'tok', onAuthError }), + ).rejects.toBeInstanceOf(SurveysApiError); + expect(onAuthError).toHaveBeenCalledTimes(1); + }); + + it('does not invoke onAuthError on non-auth errors', async () => { + (global as unknown as { fetch: jest.Mock }).fetch = mockFetch(500, {}); + const onAuthError = jest.fn(); + + await expect( + surveysGet('me', { token: 'tok', onAuthError }), + ).rejects.toBeInstanceOf(SurveysApiError); + expect(onAuthError).not.toHaveBeenCalled(); + }); + + it('does not invoke onAuthError on 401 for token-less request', async () => { + (global as unknown as { fetch: jest.Mock }).fetch = mockFetch(401, {}); + const onAuthError = jest.fn(); + + await expect(surveysGet('open/x', { onAuthError })).rejects.toBeInstanceOf( + SurveysApiError, + ); + expect(onAuthError).not.toHaveBeenCalled(); + }); +}); + +describe('isAuthError', () => { + it('matches 401/403 on SurveysApiError', () => { + expect( + isAuthError(new SurveysApiError({ message: 'x', status: 401, url: 'u' })), + ).toBe(true); + expect( + isAuthError(new SurveysApiError({ message: 'x', status: 403, url: 'u' })), + ).toBe(true); + expect( + isAuthError(new SurveysApiError({ message: 'x', status: 500, url: 'u' })), + ).toBe(false); + }); + + it('matches 401/403 on FetcherError too', () => { + expect(isAuthError(new FetcherError('x', 401))).toBe(true); + expect(isAuthError(new FetcherError('x', 500))).toBe(false); + }); + + it('returns false for non-errors', () => { + expect(isAuthError(new Error('plain'))).toBe(false); + expect(isAuthError(null)).toBe(false); + }); +}); diff --git a/modules/surveys-sdk/api/endpoints.ts b/modules/surveys-sdk/api/endpoints.ts new file mode 100644 index 000000000..62945b744 --- /dev/null +++ b/modules/surveys-sdk/api/endpoints.ts @@ -0,0 +1,26 @@ +import type { OperatorKey } from './types'; + +export const endpoints = { + nonce: 'auth/nonce', + signin: 'auth/signin', + myDelegates: 'delegates/my', + + publicSummary: (op: OperatorKey) => `open/${op}` as const, + + contacts: (op: OperatorKey) => `${op}/contacts` as const, + experience: (op: OperatorKey) => `${op}/experience` as const, + howDidYouLearnCsm: (op: OperatorKey) => + `${op}/how-did-you-learn-csm` as const, + summary: (op: OperatorKey) => `${op}/summary` as const, + setups: (op: OperatorKey, id?: string | number) => + id !== undefined ? `${op}/setups/${id}` : `${op}/setups`, + setupsKeys: (op: OperatorKey) => `${op}/setups/keys` as const, + delegates: (op: OperatorKey) => `${op}/delegates` as const, + delegate: (op: OperatorKey, address: string) => + `${op}/delegates/${address}` as const, + + icsStatus: 'ics/status', + icsApply: 'ics/apply', + dvtStatus: 'dvt/status', + dvtApply: 'dvt/apply', +} as const; diff --git a/modules/surveys-sdk/api/errors.ts b/modules/surveys-sdk/api/errors.ts new file mode 100644 index 000000000..792a25905 --- /dev/null +++ b/modules/surveys-sdk/api/errors.ts @@ -0,0 +1,33 @@ +import { FetcherError } from 'utils/fetcher-error'; + +export class SurveysApiError extends Error { + readonly status: number; + readonly url: string; + readonly body?: unknown; + readonly cause?: unknown; + + constructor(opts: { + message: string; + status: number; + url: string; + body?: unknown; + cause?: unknown; + }) { + super(opts.message); + this.name = 'SurveysApiError'; + this.status = opts.status; + this.url = opts.url; + this.body = opts.body; + this.cause = opts.cause; + } +} + +export const isAuthError = (err: unknown): boolean => { + if (err instanceof SurveysApiError) { + return err.status === 401 || err.status === 403; + } + if (err instanceof FetcherError) { + return err.status === 401 || err.status === 403; + } + return false; +}; diff --git a/modules/surveys-sdk/api/surveys-api.ts b/modules/surveys-sdk/api/surveys-api.ts new file mode 100644 index 000000000..8440d7ed4 --- /dev/null +++ b/modules/surveys-sdk/api/surveys-api.ts @@ -0,0 +1,96 @@ +import { config } from 'config'; +import { readSavedUserConfig } from 'config/user-config/saved-config'; +import { getExternalLinks } from 'consts/external-links'; +import type { + SiweNonceResponse, + SiweSigninPayload, + SiweSigninResponse, +} from 'modules/siwe'; +import invariant from 'tiny-invariant'; +import { FetcherError } from 'utils/fetcher-error'; +import { standardFetcher } from 'utils/standard-fetcher'; +import { endpoints } from './endpoints'; +import { SurveysApiError } from './errors'; +import type { SurveysFetchOptions } from './types'; +import { appendQuery, joinUrl } from './url'; + +// Resolved once at module load. Read order: localStorage QA override (set on +// the qa-config page) → `process.env.SURVEYS_API_URL` (via env-dynamics) → +// per-chain `getExternalLinks().surveyApi` default. The QA override applies +// only after a page reload, matching the qa-config form's behavior. +// May be undefined when surveys are disabled in this env; transport invariants. +export const SURVEYS_API_BASE_URL: string | undefined = + readSavedUserConfig().surveyApiUrl ?? + config.surveysApiUrl ?? + getExternalLinks().surveyApi; + +export const isSurveysApiConfigured = Boolean(SURVEYS_API_BASE_URL); + +const buildHeaders = (token?: string): Record => { + const headers: Record = { + 'Content-Type': 'application/json', + }; + if (token) headers.Authorization = token; + return headers; +}; + +const surveysRequest = async ( + path: string, + init: RequestInit, + opts: SurveysFetchOptions = {}, +): Promise => { + invariant( + SURVEYS_API_BASE_URL, + 'surveys-sdk: SURVEYS_API_BASE_URL is not configured (set SURVEYS_API_URL env or surveyApi external link)', + ); + const url = appendQuery(joinUrl(SURVEYS_API_BASE_URL, path), opts.query); + + try { + return await standardFetcher(url, { + ...init, + headers: buildHeaders(opts.token), + signal: opts.signal, + }); + } catch (err) { + if (err instanceof FetcherError) { + if (opts.token && (err.status === 401 || err.status === 403)) { + opts.onAuthError?.(); + } + throw new SurveysApiError({ + message: err.message, + status: err.status, + url, + cause: err, + }); + } + throw err; + } +}; + +export const surveysGet = ( + path: string, + opts: SurveysFetchOptions = {}, +): Promise => surveysRequest(path, { method: 'GET' }, opts); + +export const surveysPost = ( + path: string, + body: B, + opts: SurveysFetchOptions = {}, +): Promise => + surveysRequest(path, { method: 'POST', body: JSON.stringify(body) }, opts); + +export const surveysDelete = ( + path: string, + opts: SurveysFetchOptions = {}, +): Promise => surveysRequest(path, { method: 'DELETE' }, opts); + +// Public nonce endpoint — accepts no token. Pass directly to . +// Returns a server-issued, single-use nonce that must be embedded in the SIWE message. +export const surveysGetNonce = (): Promise => + surveysGet(endpoints.nonce); + +// Public signin endpoint — accepts no token. Pass directly to . +export const surveysSignin = ( + payload: SiweSigninPayload, +): Promise => + surveysPost(endpoints.signin, payload); diff --git a/modules/surveys-sdk/api/types.ts b/modules/surveys-sdk/api/types.ts new file mode 100644 index 000000000..90ecef4c0 --- /dev/null +++ b/modules/surveys-sdk/api/types.ts @@ -0,0 +1,16 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; + +type Module = Lowercase<(typeof MODULE_NAME)[keyof typeof MODULE_NAME]>; + +// Branded namespaced key, e.g. 'csm-42'. Always built via `operatorKey()`. +export type OperatorKey = `${Module}-${bigint}`; + +export type SurveysFetchOptions = { + // Bearer-style header value, e.g. `${token_type} ${access_token}`. + // Required for authenticated requests. + token?: string; + // Invoked on 401/403 before throwing. + onAuthError?: () => void; + query?: Record; + signal?: AbortSignal; +}; diff --git a/modules/surveys-sdk/api/url.ts b/modules/surveys-sdk/api/url.ts new file mode 100644 index 000000000..5d8cdbb57 --- /dev/null +++ b/modules/surveys-sdk/api/url.ts @@ -0,0 +1,40 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import type { OperatorKey } from './types'; + +type OperatorKeyFn = { + (module: MODULE_NAME, id: bigint): OperatorKey; + (module: MODULE_NAME, id: bigint | undefined): OperatorKey | undefined; +}; + +export const operatorKey: OperatorKeyFn = ( + module: MODULE_NAME, + id: bigint | undefined, +) => + (id === undefined + ? undefined + : `${module.toLowerCase()}-${id}`) as OperatorKey; + +const OPERATOR_KEY_RE = /^(csm|cm)-(\d+)$/; + +export const parseOperatorKey = (s: string): OperatorKey | null => + OPERATOR_KEY_RE.test(s) ? (s as OperatorKey) : null; + +export const joinUrl = (baseUrl: string, path: string): string => { + const base = baseUrl.replace(/\/+$/, ''); + const tail = path.replace(/^\/+/, ''); + return `${base}/${tail}`; +}; + +export const appendQuery = ( + url: string, + query?: Record, +): string => { + if (!query) return url; + const params = new URLSearchParams(); + for (const [k, v] of Object.entries(query)) { + if (v === undefined) continue; + params.append(k, String(v)); + } + const qs = params.toString(); + return qs ? `${url}?${qs}` : url; +}; diff --git a/modules/surveys-sdk/hooks/query-keys.ts b/modules/surveys-sdk/hooks/query-keys.ts new file mode 100644 index 000000000..18efe9e84 --- /dev/null +++ b/modules/surveys-sdk/hooks/query-keys.ts @@ -0,0 +1,18 @@ +import type { OperatorKey } from '../api/types'; + +// Authed paths (`auth/...`, `ics/status`, `dvt/status`, `delegates/my`) are +// namespaced by wallet address so logout / account switch invalidates the +// cache without keying on the rotating access token. +export const surveysKeys = { + all: ['surveys'] as const, + operator: (key: OperatorKey) => ['surveys', key] as const, + path: (key: OperatorKey, path: string) => ['surveys', key, path] as const, + pending: (path: string) => ['surveys', 'pending', path] as const, + summary: (key: OperatorKey) => ['surveys', key, 'summary'] as const, + public: (path: string) => ['surveys', 'public', path] as const, + auth: ['surveys', 'auth'] as const, + authPath: (path: string, address?: string) => + address + ? (['surveys', 'auth', address, path] as const) + : (['surveys', 'auth', path] as const), +}; diff --git a/modules/surveys-sdk/hooks/use-operator-key.ts b/modules/surveys-sdk/hooks/use-operator-key.ts new file mode 100644 index 000000000..37c2e08df --- /dev/null +++ b/modules/surveys-sdk/hooks/use-operator-key.ts @@ -0,0 +1,11 @@ +import { config } from 'config'; +import { useNodeOperatorId } from 'modules/web3'; +import type { OperatorKey } from '../api/types'; +import { operatorKey } from '../api/url'; + +export const useOperatorKey = ( + idOverride?: bigint, +): OperatorKey | undefined => { + const nodeOperatorId = useNodeOperatorId(); + return operatorKey(config.module, idOverride ?? nodeOperatorId); +}; diff --git a/modules/surveys-sdk/hooks/use-operator-survey.ts b/modules/surveys-sdk/hooks/use-operator-survey.ts new file mode 100644 index 000000000..fdeb84054 --- /dev/null +++ b/modules/surveys-sdk/hooks/use-operator-survey.ts @@ -0,0 +1,123 @@ +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { STRATEGY_LAZY } from 'consts'; +import { useSiweAuth } from 'modules/siwe'; +import { useCallback, useMemo } from 'react'; +import invariant from 'tiny-invariant'; +import { surveysDelete, surveysGet, surveysPost } from '../api/surveys-api'; +import type { OperatorKey } from '../api/types'; +import { useOperatorKey } from './use-operator-key'; +import { surveysKeys } from './query-keys'; + +type UseOperatorSurveyOptions = { + operatorKey?: OperatorKey; + skipFetching?: boolean; + transformIncoming?: (d: R) => T; + transformOutgoing?: (d: T) => R; + invalidateOnMutate?: boolean; +}; + +export const useOperatorSurvey = ( + path: string, + opts: UseOperatorSurveyOptions = {}, +) => { + const { token, logout } = useSiweAuth(); + const queryClient = useQueryClient(); + const connectedKey = useOperatorKey(); + const effectiveKey = opts.operatorKey ?? connectedKey; + + const url = effectiveKey ? `${effectiveKey}/${path}` : undefined; + + const queryKey = useMemo( + () => + effectiveKey + ? surveysKeys.path(effectiveKey, path) + : surveysKeys.pending(path), + [effectiveKey, path], + ); + + const { transformIncoming, transformOutgoing, invalidateOnMutate } = opts; + + const requireUrl = (): string => { + invariant(url, 'useOperatorSurvey: operator key is not available'); + return url; + }; + + const query = useQuery({ + queryKey, + queryFn: async ({ signal }) => { + const res = await surveysGet(requireUrl(), { + token, + onAuthError: logout, + signal, + }); + return res && transformIncoming + ? transformIncoming(res) + : (res as unknown as T); + }, + enabled: !opts.skipFetching && effectiveKey !== undefined && !!token, + ...STRATEGY_LAZY, + }); + + const updateMutation = useMutation({ + mutationFn: async (data: T): Promise => { + const payload = transformOutgoing ? transformOutgoing(data) : data; + const res = await surveysPost(requireUrl(), payload, { + token, + onAuthError: logout, + }); + return res && transformIncoming + ? transformIncoming(res) + : (res as unknown as T); + }, + onSuccess: (result) => { + if (invalidateOnMutate) { + void queryClient.invalidateQueries({ queryKey }); + } else { + queryClient.setQueryData(queryKey, result); + } + if (effectiveKey) { + void queryClient.invalidateQueries({ + queryKey: surveysKeys.summary(effectiveKey), + }); + } + }, + }); + + const deleteMutation = useMutation({ + mutationFn: async (): Promise => { + await surveysDelete(requireUrl(), { token, onAuthError: logout }); + }, + onSuccess: () => { + if (effectiveKey) { + void queryClient.invalidateQueries({ + queryKey: surveysKeys.operator(effectiveKey), + }); + } + }, + }); + + const mutate = useCallback( + (data?: T) => { + if (data === undefined) { + void queryClient.invalidateQueries({ queryKey }); + return Promise.resolve(); + } + return updateMutation.mutateAsync(data); + }, + [queryClient, queryKey, updateMutation], + ); + + const remove = useCallback( + () => deleteMutation.mutateAsync(), + [deleteMutation], + ); + + return { + data: query.data, + error: query.error, + isLoading: query.isLoading, + initialLoading: query.isLoading && query.isFetching, + mutate, + remove, + }; +}; diff --git a/modules/surveys-sdk/hooks/use-public-survey.ts b/modules/surveys-sdk/hooks/use-public-survey.ts new file mode 100644 index 000000000..2f2de338c --- /dev/null +++ b/modules/surveys-sdk/hooks/use-public-survey.ts @@ -0,0 +1,14 @@ +import { useQuery, UseQueryResult } from '@tanstack/react-query'; +import { STRATEGY_LAZY } from 'consts'; +import { surveysGet } from '../api/surveys-api'; +import { surveysKeys } from './query-keys'; + +// Public GET wrapper — no token, callable from any context (no SiweAuthProvider needed). +export const usePublicSurvey = (path: string | null): UseQueryResult => { + return useQuery({ + queryKey: surveysKeys.public(path ?? ''), + queryFn: ({ signal }) => surveysGet(path as string, { signal }), + enabled: Boolean(path), + ...STRATEGY_LAZY, + }); +}; diff --git a/modules/surveys-sdk/hooks/use-surveys-mutation.ts b/modules/surveys-sdk/hooks/use-surveys-mutation.ts new file mode 100644 index 000000000..ffefc9c41 --- /dev/null +++ b/modules/surveys-sdk/hooks/use-surveys-mutation.ts @@ -0,0 +1,47 @@ +import { + useMutation, + UseMutationResult, + useQueryClient, +} from '@tanstack/react-query'; +import { useSiweAuth } from 'modules/siwe'; +import invariant from 'tiny-invariant'; +import { surveysDelete, surveysPost } from '../api/surveys-api'; + +type UseSurveysMutationOptions = { + method?: 'POST' | 'DELETE'; // default 'POST' + mutationKey?: unknown[]; // keys to invalidate on success + invalidate?: readonly (readonly unknown[])[]; + onSuccess?: (result: T, vars: B) => void; + onError?: (err: unknown, vars: B) => void; +}; + +export const useSurveysMutation = ( + path: string | ((vars: B) => string), + opts: UseSurveysMutationOptions = {}, +): UseMutationResult => { + const { token, logout } = useSiweAuth(); + const queryClient = useQueryClient(); + const method = opts.method ?? 'POST'; + + return useMutation({ + mutationKey: opts.mutationKey, + mutationFn: async (vars: B) => { + const resolvedPath = typeof path === 'function' ? path(vars) : path; + invariant(resolvedPath, 'useSurveysMutation: path is empty'); + const fetchOpts = { token, onAuthError: logout }; + if (method === 'DELETE') { + return surveysDelete(resolvedPath, fetchOpts); + } + return surveysPost(resolvedPath, vars, fetchOpts); + }, + onSuccess: (result, vars) => { + if (opts.invalidate) { + for (const key of opts.invalidate) { + void queryClient.invalidateQueries({ queryKey: key }); + } + } + opts.onSuccess?.(result, vars); + }, + onError: opts.onError, + }); +}; diff --git a/modules/surveys-sdk/hooks/use-surveys-query.ts b/modules/surveys-sdk/hooks/use-surveys-query.ts new file mode 100644 index 000000000..66fbddc3a --- /dev/null +++ b/modules/surveys-sdk/hooks/use-surveys-query.ts @@ -0,0 +1,46 @@ +import { useQuery, UseQueryResult } from '@tanstack/react-query'; +import { STRATEGY_LAZY } from 'consts'; +import { useSiweAuth } from 'modules/siwe'; +import { useDappStatus } from 'modules/web3'; +import { useMemo } from 'react'; +import { surveysGet } from '../api/surveys-api'; +import { surveysKeys } from './query-keys'; + +type StaleStrategy = { + staleTime?: number; + refetchOnWindowFocus?: boolean; + refetchOnReconnect?: boolean; + refetchInterval?: number | false; +}; + +type UseSurveysQueryOptions = { + enabled?: boolean; + queryKey?: readonly unknown[]; + select?: (d: T) => S; + staleStrategy?: StaleStrategy; +}; + +export const useSurveysQuery = ( + path: string, + opts: UseSurveysQueryOptions = {}, +): UseQueryResult => { + const { token, logout } = useSiweAuth(); + const { address } = useDappStatus(); + + const queryKey = useMemo( + () => opts.queryKey ?? surveysKeys.authPath(path, address), + [opts.queryKey, path, address], + ); + + const enabled = opts.enabled !== undefined ? opts.enabled : !!token; + const strategy = opts.staleStrategy ?? STRATEGY_LAZY; + + return useQuery({ + queryKey, + queryFn: ({ signal }) => + surveysGet(path, { token, onAuthError: logout, signal }), + enabled, + select: opts.select, + ...strategy, + }); +}; diff --git a/modules/surveys-sdk/index.ts b/modules/surveys-sdk/index.ts new file mode 100644 index 000000000..d33af58ba --- /dev/null +++ b/modules/surveys-sdk/index.ts @@ -0,0 +1,19 @@ +export { + SURVEYS_API_BASE_URL, + isSurveysApiConfigured, + surveysDelete, + surveysGet, + surveysPost, +} from './api/surveys-api'; +export { SurveysAuthProvider } from './surveys-auth-provider'; +export { operatorKey, parseOperatorKey } from './api/url'; +export { endpoints } from './api/endpoints'; +export { SurveysApiError, isAuthError } from './api/errors'; +export type { OperatorKey, SurveysFetchOptions } from './api/types'; + +export { useOperatorKey } from './hooks/use-operator-key'; +export { useOperatorSurvey } from './hooks/use-operator-survey'; +export { useSurveysQuery } from './hooks/use-surveys-query'; +export { useSurveysMutation } from './hooks/use-surveys-mutation'; +export { usePublicSurvey } from './hooks/use-public-survey'; +export { surveysKeys } from './hooks/query-keys'; diff --git a/modules/surveys-sdk/surveys-auth-provider.tsx b/modules/surveys-sdk/surveys-auth-provider.tsx new file mode 100644 index 000000000..87bdb4e66 --- /dev/null +++ b/modules/surveys-sdk/surveys-auth-provider.tsx @@ -0,0 +1,11 @@ +import { SiweAuthProvider } from 'modules/siwe'; +import { FC, PropsWithChildren } from 'react'; +import { surveysGetNonce, surveysSignin } from './api/surveys-api'; + +// SIWE auth bound to the surveys API. Shared by the surveys, ICS, and DVT flows, +// which all authenticate against the same backend with one interchangeable token. +export const SurveysAuthProvider: FC = ({ children }) => ( + + {children} + +); diff --git a/modules/web3/hooks/index.ts b/modules/web3/hooks/index.ts new file mode 100644 index 000000000..551012433 --- /dev/null +++ b/modules/web3/hooks/index.ts @@ -0,0 +1,60 @@ +export * from './use-balance'; +export * from './use-bond-by-keys-count'; +export * from './use-bond-next-keys-count'; +export * from './use-curated-gates-eligibility'; +export * from './use-curve-parameters'; +export * from './use-custom-rewards-claimer'; +export * from './use-dapp-status'; +export * from './use-default-curve-id'; +export * from './use-deposit-queue-batches'; +export * from './use-fee-splits'; +export * from './use-frame-info'; +export * from './use-has-priority-queue-spots'; +export * from './use-has-report-delayed-penalty-role'; +export * from './use-ics-curve-id'; +export * from './use-ics-paused'; +export * from './use-ics-proof'; +export * from './use-idvtc-curve-id'; +export * from './use-idvtc-paused'; +export * from './use-idvtc-proof'; +export * from './use-invites'; +export * from './use-is-contract'; +export * from './use-is-lock-expired'; +export * from './use-key-eject-fee'; +export * from './use-key-removal-fee'; +export * from './use-last-report-timestamps'; +export * from './use-last-report-tx-hash'; +export * from './use-max-gas-price'; +export * from './use-operator-balance'; +export * from './use-operator-curve-id'; +export * from './use-operator-group'; +export * from './use-operator-group-id'; +export * from './use-operator-group-stake-summary'; +export * from './use-operator-info'; +export * from './use-operator-is-owner'; +export * from './use-operator-keys-with-issues'; +export * from './use-operator-keys-with-status'; +export * from './use-operator-keys-with-strikes'; +export * from './use-operator-keys-with-wrong-fee-recipient'; +export * from './use-operator-last-rewards'; +export * from './use-operator-metadata'; +export * from './use-operator-owner'; +export * from './use-operator-penalties'; +export * from './use-operator-reward'; +export * from './use-operator-rewards-history'; +export * from './use-operator-short-info'; +export * from './use-operator-stake-summary'; +export * from './use-operator-type'; +export * from './use-operator-weight'; +export * from './use-operators-count'; +export * from './use-operators-with-locked-bond'; +export * from './use-other-module'; +export * from './use-share-limit-percentage'; +export * from './use-share-limit-status'; +export * from './use-share-limit'; +export * from './use-sm-status'; +export * from './use-stETH-by-wstETH'; +export * from './use-stake-limit'; +export * from './use-steth-pool-data'; +export * from './use-tx-confirmation'; +export * from './use-wstETH-by-stETH'; diff --git a/modules/web3/hooks/use-balance.ts b/modules/web3/hooks/use-balance.ts new file mode 100644 index 000000000..ef7949c8b --- /dev/null +++ b/modules/web3/hooks/use-balance.ts @@ -0,0 +1,249 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { useQuery, useQueryClient, type QueryKey } from '@tanstack/react-query'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { + useConnection, + useBalance, + useReadContract, + useWatchContractEvent, +} from 'wagmi'; + +import { config } from 'config'; +import { useDappStatus, useLidoSDK } from 'modules/web3'; + +import { + erc20abi, + type AbstractLidoSDKErc20, +} from '@lidofinance/lido-ethereum-sdk/erc20'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import { + getAbiItem, + type Address, + type WatchContractEventOnLogsFn, +} from 'viem'; +import type { GetBalanceData } from 'wagmi/query'; + +const selectBalance = (data: GetBalanceData) => data.value; + +export const useEthereumBalance = () => { + const { address, isAccountActive } = useDappStatus(); + + return useBalance({ + address, + query: { + select: selectBalance, + staleTime: config.PROVIDER_POLLING_INTERVAL, + refetchInterval: config.PROVIDER_POLLING_INTERVAL, + enabled: isAccountActive, + }, + }); +}; + +type TokenContract = Awaited< + ReturnType['getContract']> +>; + +type TokenSubscriptionState = Record< + Address, + { + subscribers: number; + queryKey: QueryKey; + } +>; + +type SubscribeArgs = { + tokenAddress: Address; + queryKey: QueryKey; +}; + +type UseBalanceProps = { + shouldSubscribeToUpdates?: boolean; +}; + +export const Erc20EventsAbi = [ + getAbiItem({ + abi: erc20abi, + name: 'Transfer', + }), +]; + +type OnLogsFn = WatchContractEventOnLogsFn< + typeof Erc20EventsAbi, + 'Transfer', + true +>; + +const onError = (error: unknown) => + console.warn( + '[useTokenTransferSubscription] error while watching events', + error, + ); + +export const useTokenTransferSubscription = () => { + const { address } = useConnection(); + const queryClient = useQueryClient(); + const [subscriptions, setSubscriptions] = useState( + {}, + ); + + const tokens = useMemo( + () => Object.keys(subscriptions) as Address[], + [subscriptions], + ); + + const onLogs: OnLogsFn = useCallback( + (logs) => { + for (const log of logs) { + const subscription = + subscriptions[log.address.toLowerCase() as Address]; + if (!subscription) continue; + // we could optimistically update balance data + // but it's easier to refetch balance after transfer + void queryClient.invalidateQueries( + { + queryKey: subscription.queryKey, + }, + { cancelRefetch: false }, + ); + } + }, + [queryClient, subscriptions], + ); + + const shouldWatch = !!(address && tokens.length > 0); + + useWatchContractEvent({ + abi: Erc20EventsAbi, + eventName: 'Transfer', + batch: true, + poll: true, + args: useMemo( + () => ({ + to: address, + }), + [address], + ), + address: tokens, + enabled: shouldWatch, + onLogs, + onError, + }); + + useWatchContractEvent({ + abi: Erc20EventsAbi, + eventName: 'Transfer', + batch: true, + poll: true, + args: useMemo( + () => ({ + from: address, + }), + [address], + ), + address: tokens, + enabled: shouldWatch, + onLogs, + onError, + }); + + const subscribe = useCallback( + ({ tokenAddress: _tokenAddress, queryKey }: SubscribeArgs) => { + const tokenAddress = _tokenAddress.toLowerCase() as Address; + setSubscriptions((old) => { + const existing = old[tokenAddress]; + return { + ...old, + [tokenAddress]: { + queryKey, + subscribers: existing?.subscribers ?? 0 + 1, + }, + }; + }); + + // returns unsubscribe to be used as useEffect return fn (for unmount) + return () => { + setSubscriptions((old) => { + const existing = old[tokenAddress]; + if (!existing) return old; + if (existing.subscribers > 1) { + return { + ...old, + [tokenAddress]: { + ...existing, + subscribers: existing.subscribers - 1, + }, + }; + } else { + delete old[tokenAddress]; + return { ...old }; + } + }); + }; + }, + [], + ); + + return subscribe; +}; + +// NB: contract can be undefined but for better wagmi typings is casted as NoNNullable +const useTokenBalance = (contract: TokenContract, shouldSubscribe = true) => { + const { isAccountActive, address } = useDappStatus(); + const subscribe = useTokenTransferSubscription(); + + const balanceQuery = useReadContract({ + abi: contract?.abi, + address: contract?.address, + functionName: 'balanceOf', + args: address && [address], + query: { + enabled: isAccountActive, + // because we update on events we can have high staleTime + // this prevents loader when changing pages + // but safes us from laggy user RPCs + staleTime: config.PROVIDER_POLLING_INTERVAL * 2, + refetchInterval: config.PROVIDER_POLLING_INTERVAL * 2, + }, + }); + + useEffect(() => { + if (shouldSubscribe && isAccountActive && contract?.address) { + return subscribe({ + tokenAddress: contract.address, + queryKey: balanceQuery.queryKey, + }); + } + // queryKey causes rerender + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isAccountActive, contract?.address]); + + return balanceQuery; +}; + +export const useStethBalance = ({ + shouldSubscribeToUpdates = true, +}: UseBalanceProps = {}) => { + const { stETH } = useLidoSDK(); + + const { data: contract } = useQuery({ + queryKey: ['steth-contract'], + ...STRATEGY_IMMUTABLE, + queryFn: async () => stETH.getContract(), + }); + + return useTokenBalance(contract!, shouldSubscribeToUpdates); +}; + +export const useWstethBalance = ({ + shouldSubscribeToUpdates = true, +}: UseBalanceProps = {}) => { + const { wstETH } = useLidoSDK(); + + const { data: contract } = useQuery({ + queryKey: ['wsteth-contract'], + ...STRATEGY_IMMUTABLE, + queryFn: () => wstETH.getContract(), + }); + + return useTokenBalance(contract!, shouldSubscribeToUpdates); +}; diff --git a/modules/web3/hooks/use-bond-by-keys-count.ts b/modules/web3/hooks/use-bond-by-keys-count.ts new file mode 100644 index 000000000..12c5c5c35 --- /dev/null +++ b/modules/web3/hooks/use-bond-by-keys-count.ts @@ -0,0 +1,33 @@ +import { TOKENS } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +type Props = { + curveId: bigint | undefined; + keysCount?: number; + token?: TOKENS; +}; + +export const useBondByKeysCount = ({ + keysCount = 0, + curveId, + token = TOKENS.steth, +}: Props) => { + const { accounting } = useSmSDK(); + + return useQuery({ + queryKey: ['getBondAmountByKeysCountPerToken', { keysCount, curveId }], + ...STRATEGY_IMMUTABLE, + queryFn: () => { + invariant(curveId !== undefined); + return accounting.getBondAmountByKeysCountPerToken({ + keysCount: BigInt(keysCount), + curveId, + }); + }, + enabled: curveId !== undefined, + select: (data) => data[token], + }); +}; diff --git a/modules/web3/hooks/use-bond-next-keys-count.ts b/modules/web3/hooks/use-bond-next-keys-count.ts new file mode 100644 index 000000000..199334c4d --- /dev/null +++ b/modules/web3/hooks/use-bond-next-keys-count.ts @@ -0,0 +1,33 @@ +import { NodeOperatorId, TOKENS } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +type Props = { + nodeOperatorId: NodeOperatorId | undefined; + token: TOKENS; + keysCount?: number; +}; + +export const useBondNextKeysCount = ({ + nodeOperatorId, + token, + keysCount = 0, +}: Props) => { + const { accounting } = useSmSDK(); + + return useQuery({ + queryKey: ['getBondForNextKeysPerToken', { keysCount, nodeOperatorId }], + ...STRATEGY_IMMUTABLE, + queryFn: () => { + invariant(nodeOperatorId !== undefined); + return accounting.getBondForNextKeysPerToken({ + keysCount: BigInt(keysCount), + nodeOperatorId, + }); + }, + enabled: keysCount > 0 && nodeOperatorId !== undefined, + select: (data) => data[token], + }); +}; diff --git a/modules/web3/hooks/use-curated-gates-eligibility.ts b/modules/web3/hooks/use-curated-gates-eligibility.ts new file mode 100644 index 000000000..6ab3d1de6 --- /dev/null +++ b/modules/web3/hooks/use-curated-gates-eligibility.ts @@ -0,0 +1,31 @@ +import { GateItemEligibility, MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; +import { useDappStatus } from './use-dapp-status'; +import { Address } from 'viem'; + +export const KEY_CURATED_GATES_PROOF = ['curated-gates-proof']; + +export const useCuratedGatesEligibility = ( + customAddress?: Address, + select?: (data: GateItemEligibility[]) => TData, +) => { + const { address: dappAddress } = useDappStatus(); + const address = customAddress ?? dappAddress; + const sdk = useSmSDK(MODULE_NAME.CM); + + return useQuery({ + queryKey: [...KEY_CURATED_GATES_PROOF, { address }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(sdk); + invariant(address); + const data = await sdk.curatedGates.getEligibility(address); + return data.filter((gate) => !!gate.isEligible); + }, + select, + enabled: !!sdk && !!address, + }); +}; diff --git a/modules/web3/hooks/use-curve-parameters.ts b/modules/web3/hooks/use-curve-parameters.ts new file mode 100644 index 000000000..f588c6e76 --- /dev/null +++ b/modules/web3/hooks/use-curve-parameters.ts @@ -0,0 +1,23 @@ +import { CurveParameters } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const useCurveParameters = ( + curveId: bigint | undefined, + select?: (data: CurveParameters) => TData, +) => { + const { parameters } = useSmSDK(); + + return useQuery({ + queryKey: ['curve-parameters', { curveId }], + ...STRATEGY_IMMUTABLE, + queryFn: () => { + invariant(curveId !== undefined); + return parameters.getAll(curveId); + }, + enabled: curveId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-custom-rewards-claimer.ts b/modules/web3/hooks/use-custom-rewards-claimer.ts new file mode 100644 index 000000000..10ef15ce4 --- /dev/null +++ b/modules/web3/hooks/use-custom-rewards-claimer.ts @@ -0,0 +1,23 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_CUSTOM_REWARDS_CLAIMER = ['custom-rewards-claimer']; + +export const useCustomRewardsClaimer = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + const { operator } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_CUSTOM_REWARDS_CLAIMER, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(nodeOperatorId !== undefined); + return await operator.getCustomRewardsClaimer(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-dapp-status.ts b/modules/web3/hooks/use-dapp-status.ts new file mode 100644 index 000000000..4b6c8c583 --- /dev/null +++ b/modules/web3/hooks/use-dapp-status.ts @@ -0,0 +1,40 @@ +import { SUPPORTED_CHAINS } from '@lidofinance/lido-csm-sdk'; +import { useUserConfig } from 'config/user-config'; +import { Address } from 'viem'; +import { useConnection } from 'wagmi'; + +type Result = { + chainId: SUPPORTED_CHAINS; + isSupportedChain: boolean; + isAccountActive: boolean; + isWalletConnected: boolean; + address?: Address; +}; + +export const useDappStatus = (): Result => { + const { + address: walletAddress, + chainId: walletChainId, + isConnected: isWalletConnected, + } = useConnection(); + + const { defaultChain: chainId } = useUserConfig(); + + const isSupportedChain = walletChainId ? walletChainId === chainId : true; + + const isAccountActive = walletChainId + ? isWalletConnected && isSupportedChain + : false; + + const address = isSupportedChain ? walletAddress : undefined; + + // no useMemo because memoisation is more expensive than boolean flags + // hook is used in many places and every usage would create separate memoisation + return { + chainId, + isSupportedChain, + isAccountActive, + isWalletConnected, + address, + }; +}; diff --git a/modules/web3/hooks/use-default-curve-id.ts b/modules/web3/hooks/use-default-curve-id.ts new file mode 100644 index 000000000..1b00ceb23 --- /dev/null +++ b/modules/web3/hooks/use-default-curve-id.ts @@ -0,0 +1,19 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const useDefaultCurveId = () => { + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: ['default-curve-id'], + ...STRATEGY_IMMUTABLE, + queryFn: () => { + invariant(sdk); + return sdk.permissionlessGate.getCurveId(); + }, + enabled: !!sdk, + }); +}; diff --git a/modules/web3/hooks/use-deposit-queue-batches.ts b/modules/web3/hooks/use-deposit-queue-batches.ts new file mode 100644 index 000000000..e302fb626 --- /dev/null +++ b/modules/web3/hooks/use-deposit-queue-batches.ts @@ -0,0 +1,24 @@ +import { DepositQueueBatch, MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_DEPOSIT_QUEUE_BATCHES = ['deposit-queue-batches']; + +export const useDepositQueueBatches = ( + select?: (data: DepositQueueBatch[][]) => TData, +) => { + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: [...KEY_DEPOSIT_QUEUE_BATCHES], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(sdk); + return sdk.depositQueue.getAllBatches(); + }, + select, + enabled: !!sdk, + }); +}; diff --git a/modules/web3/hooks/use-fee-splits.ts b/modules/web3/hooks/use-fee-splits.ts new file mode 100644 index 000000000..2a499404c --- /dev/null +++ b/modules/web3/hooks/use-fee-splits.ts @@ -0,0 +1,21 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_FEE_SPLITS = ['fee-splits']; + +export const useFeeSplits = (nodeOperatorId: NodeOperatorId | undefined) => { + const { operator } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_FEE_SPLITS, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(nodeOperatorId !== undefined); + return await operator.getFeeSplits(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-frame-info.ts b/modules/web3/hooks/use-frame-info.ts new file mode 100644 index 000000000..739640a23 --- /dev/null +++ b/modules/web3/hooks/use-frame-info.ts @@ -0,0 +1,21 @@ +import { FrameInfo } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useSmSDK } from '../web3-provider'; +import { formatDate, isDayInPast } from 'utils'; + +export const useFrameInfo = ( + select?: (data: FrameInfo) => TData, +) => { + const { frame } = useSmSDK(); + + return useQuery({ + queryKey: ['frame-info'], + ...STRATEGY_CONSTANT, + queryFn: () => frame.getInfo(), + select, + }); +}; + +export const getNextDistribution = (data: FrameInfo) => + isDayInPast(data.nextReport) ? 'soon' : `on ${formatDate(data.nextReport)}`; diff --git a/modules/web3/hooks/use-has-priority-queue-spots.ts b/modules/web3/hooks/use-has-priority-queue-spots.ts new file mode 100644 index 000000000..e9049511e --- /dev/null +++ b/modules/web3/hooks/use-has-priority-queue-spots.ts @@ -0,0 +1,25 @@ +import { CurveParameters } from '@lidofinance/lido-csm-sdk'; +import { useCallback } from 'react'; +import { useCurrentCurveId } from 'shared/hooks'; +import { canAddMorePriorityKeys } from 'utils/curve-parameters'; +import { useNodeOperatorId } from '../operator-provider'; +import { useCurveParameters } from './use-curve-parameters'; +import { useOperatorInfo } from './use-operator-info'; + +export const useHasPriorityQueueSpots = () => { + const nodeOperatorId = useNodeOperatorId(); + const curveId = useCurrentCurveId(); + const { data: operatorInfo } = useOperatorInfo(nodeOperatorId); + + const selectHasPrioritySpots = useCallback( + (curveParameters: CurveParameters) => { + if (nodeOperatorId !== undefined && operatorInfo) { + return canAddMorePriorityKeys(operatorInfo, curveParameters); + } + return curveParameters.queueConfig.maxDeposits > 0; + }, + [nodeOperatorId, operatorInfo], + ); + + return useCurveParameters(curveId, selectHasPrioritySpots); +}; diff --git a/modules/web3/hooks/use-has-report-delayed-penalty-role.ts b/modules/web3/hooks/use-has-report-delayed-penalty-role.ts new file mode 100644 index 000000000..46e95a881 --- /dev/null +++ b/modules/web3/hooks/use-has-report-delayed-penalty-role.ts @@ -0,0 +1,20 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; +import { useDappStatus } from './use-dapp-status'; + +export const useHasReportDelayedPenaltyRole = () => { + const { address } = useDappStatus(); + const { delayedPenalty } = useSmSDK(); + + return useQuery({ + queryKey: ['has-report-delayed-penalty-role', { address }], + ...STRATEGY_IMMUTABLE, + queryFn: () => { + invariant(address); + return delayedPenalty.hasReportRole(address); + }, + enabled: !!address, + }); +}; diff --git a/modules/web3/hooks/use-ics-curve-id.ts b/modules/web3/hooks/use-ics-curve-id.ts new file mode 100644 index 000000000..e384bd305 --- /dev/null +++ b/modules/web3/hooks/use-ics-curve-id.ts @@ -0,0 +1,19 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const useIcsCurveId = () => { + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: ['ics-curve-id'], + ...STRATEGY_IMMUTABLE, + queryFn: () => { + invariant(sdk); + return sdk.icsGate.getCurveId(); + }, + enabled: !!sdk, + }); +}; diff --git a/modules/web3/hooks/use-ics-paused.ts b/modules/web3/hooks/use-ics-paused.ts new file mode 100644 index 000000000..852936326 --- /dev/null +++ b/modules/web3/hooks/use-ics-paused.ts @@ -0,0 +1,19 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const useIcsPaused = () => { + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: ['ics-paused'], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(sdk); + return sdk.icsGate.isPaused(); + }, + enabled: !!sdk, + }); +}; diff --git a/modules/web3/hooks/use-ics-proof.ts b/modules/web3/hooks/use-ics-proof.ts new file mode 100644 index 000000000..bc974b47b --- /dev/null +++ b/modules/web3/hooks/use-ics-proof.ts @@ -0,0 +1,26 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { Address } from 'viem'; +import { useSmSDK } from '../web3-provider'; +import { useDappStatus } from './use-dapp-status'; + +export const KEY_ICS_PROOF = ['ics-proof']; + +export const useIcsProof = (customAddress?: Address) => { + const { address: dappAddress } = useDappStatus(); + const address = customAddress ?? dappAddress; + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: [...KEY_ICS_PROOF, { address }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(sdk); + invariant(address); + return sdk.icsGate.getProofAndConsumed(address); + }, + enabled: !!sdk && !!address, + }); +}; diff --git a/modules/web3/hooks/use-idvtc-curve-id.ts b/modules/web3/hooks/use-idvtc-curve-id.ts new file mode 100644 index 000000000..bb97c205a --- /dev/null +++ b/modules/web3/hooks/use-idvtc-curve-id.ts @@ -0,0 +1,19 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const useIdvtcCurveId = () => { + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: ['idvtc-curve-id'], + ...STRATEGY_IMMUTABLE, + queryFn: () => { + invariant(sdk); + return sdk.idvtcGate.getCurveId(); + }, + enabled: !!sdk, + }); +}; diff --git a/modules/web3/hooks/use-idvtc-paused.ts b/modules/web3/hooks/use-idvtc-paused.ts new file mode 100644 index 000000000..36446f5bf --- /dev/null +++ b/modules/web3/hooks/use-idvtc-paused.ts @@ -0,0 +1,19 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const useIdvtcPaused = () => { + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: ['idvtc-paused'], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(sdk); + return sdk.idvtcGate.isPaused(); + }, + enabled: !!sdk, + }); +}; diff --git a/modules/web3/hooks/use-idvtc-proof.ts b/modules/web3/hooks/use-idvtc-proof.ts new file mode 100644 index 000000000..2cae72abb --- /dev/null +++ b/modules/web3/hooks/use-idvtc-proof.ts @@ -0,0 +1,26 @@ +import { MODULE_NAME } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { Address } from 'viem'; +import { useSmSDK } from '../web3-provider'; +import { useDappStatus } from './use-dapp-status'; + +export const KEY_IDVTC_PROOF = ['idvtc-proof']; + +export const useIdvtcProof = (customAddress?: Address) => { + const { address: dappAddress } = useDappStatus(); + const address = customAddress ?? dappAddress; + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: [...KEY_IDVTC_PROOF, { address }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(sdk); + invariant(address); + return sdk.idvtcGate.getProofAndConsumed(address); + }, + enabled: !!sdk && !!address, + }); +}; diff --git a/modules/web3/hooks/use-invites.ts b/modules/web3/hooks/use-invites.ts new file mode 100644 index 000000000..a13f41356 --- /dev/null +++ b/modules/web3/hooks/use-invites.ts @@ -0,0 +1,24 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; +import { useDappStatus } from './use-dapp-status'; +import { Address } from 'viem'; + +export const KEY_INVITES = ['invites']; + +export const useInvites = (customAddress?: Address) => { + const { address: dappAddress } = useDappStatus(); + const address = customAddress ?? dappAddress; + const { discovery } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_INVITES, { address }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(address); + return discovery.getNodeOperatorsByProposedAddress(address); + }, + enabled: !!address, + }); +}; diff --git a/modules/web3/hooks/use-is-contract.ts b/modules/web3/hooks/use-is-contract.ts new file mode 100644 index 000000000..290dc184d --- /dev/null +++ b/modules/web3/hooks/use-is-contract.ts @@ -0,0 +1,19 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_IMMUTABLE } from 'consts'; +import { useLidoSDK } from 'modules/web3'; +import invariant from 'tiny-invariant'; +import { Address } from 'viem'; + +export const useIsContract = (address: Address | undefined) => { + const { core } = useLidoSDK(); + + return useQuery({ + queryKey: ['use-is-contract', address], + ...STRATEGY_IMMUTABLE, + queryFn: () => { + invariant(address); + return core.isContract(address); + }, + enabled: !!address, + }); +}; diff --git a/modules/web3/hooks/use-is-lock-expired.ts b/modules/web3/hooks/use-is-lock-expired.ts new file mode 100644 index 000000000..96fb186c3 --- /dev/null +++ b/modules/web3/hooks/use-is-lock-expired.ts @@ -0,0 +1,23 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_IS_LOCK_EXPIRED = ['is-lock-expired']; + +export const useIsLockExpired = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + const { operator } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_IS_LOCK_EXPIRED, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(nodeOperatorId !== undefined); + return operator.isLockExpired(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-key-eject-fee.ts b/modules/web3/hooks/use-key-eject-fee.ts new file mode 100644 index 000000000..537d91c63 --- /dev/null +++ b/modules/web3/hooks/use-key-eject-fee.ts @@ -0,0 +1,13 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useSmSDK } from '../web3-provider'; + +export const useKeyEjectFee = () => { + const { keys } = useSmSDK(); + + return useQuery({ + queryKey: ['ics-eject-fee'], + queryFn: () => keys.getEjectFeePerKey(), + ...STRATEGY_CONSTANT, + }); +}; diff --git a/modules/web3/hooks/use-key-removal-fee.ts b/modules/web3/hooks/use-key-removal-fee.ts new file mode 100644 index 000000000..f67708d25 --- /dev/null +++ b/modules/web3/hooks/use-key-removal-fee.ts @@ -0,0 +1,5 @@ +import { useCurveParameters } from './use-curve-parameters'; + +export const useKeyRemovalFee = (curveId: bigint | undefined) => { + return useCurveParameters(curveId, (parameters) => parameters.keyRemovalFee); +}; diff --git a/modules/web3/hooks/use-last-report-timestamps.ts b/modules/web3/hooks/use-last-report-timestamps.ts new file mode 100644 index 000000000..7ee45a138 --- /dev/null +++ b/modules/web3/hooks/use-last-report-timestamps.ts @@ -0,0 +1,17 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useSmSDK } from '../web3-provider'; +import { ReportTimestamps } from '@lidofinance/lido-csm-sdk'; + +export const useLastReportTimestamps = ( + select?: (data: ReportTimestamps | undefined) => TData, +) => { + const { rewards } = useSmSDK(); + + return useQuery({ + queryKey: ['last-report-timestamps'], + ...STRATEGY_CONSTANT, + queryFn: () => rewards.getLastReportTimestamps(), + select, + }); +}; diff --git a/modules/web3/hooks/use-last-report-tx-hash.ts b/modules/web3/hooks/use-last-report-tx-hash.ts new file mode 100644 index 000000000..e02b36ba3 --- /dev/null +++ b/modules/web3/hooks/use-last-report-tx-hash.ts @@ -0,0 +1,13 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useSmSDK } from '../web3-provider'; + +export const useLastReportTxHash = () => { + const { rewards } = useSmSDK(); + + return useQuery({ + queryKey: ['last-report-tx-hash'], + ...STRATEGY_CONSTANT, + queryFn: () => rewards.getLastReportTransactionHash(), + }); +}; diff --git a/modules/web3/hooks/use-max-gas-price.ts b/modules/web3/hooks/use-max-gas-price.ts new file mode 100644 index 000000000..2b04be175 --- /dev/null +++ b/modules/web3/hooks/use-max-gas-price.ts @@ -0,0 +1,54 @@ +import { useFeeHistory } from 'wagmi'; +import type { GetFeeHistoryReturnType } from 'viem'; + +import { useDappStatus } from 'modules/web3'; + +const REWARD_PERCENTILES = [25]; + +const feeHistoryToMaxFee = ({ + reward, + baseFeePerGas, +}: GetFeeHistoryReturnType) => { + const maxPriorityFeePerGas = reward + ? reward?.map((fees) => fees[0]).reduce((sum, fee) => sum + fee) / + BigInt(reward.length) + : 0n; + + const lastBaseFeePerGas = baseFeePerGas[0]; + + // we have to multiply by 2 until we find a reliable way to predict baseFee change + return lastBaseFeePerGas * 2n + maxPriorityFeePerGas; +}; + +// TODO: rework +export const useMaxGasPrice = (chainId?: number) => { + const { chainId: dappChainId } = useDappStatus(); + + const { data, isLoading, error, isFetching, refetch } = useFeeHistory({ + blockCount: 5, + blockTag: 'pending', + chainId: chainId || dappChainId, + rewardPercentiles: REWARD_PERCENTILES, + query: { + select: feeHistoryToMaxFee, + }, + }); + + return { + get maxGasPrice() { + return data; + }, + get isLoading() { + return isLoading; + }, + get error() { + return error; + }, + get isFetching() { + return isFetching; + }, + update() { + return refetch(); + }, + }; +}; diff --git a/modules/web3/hooks/use-operator-balance.ts b/modules/web3/hooks/use-operator-balance.ts new file mode 100644 index 000000000..ce17b8b4c --- /dev/null +++ b/modules/web3/hooks/use-operator-balance.ts @@ -0,0 +1,25 @@ +import { BondBalance, NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_BALANCE = ['operator-balance']; + +export const useOperatorBalance = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: BondBalance) => TData, +) => { + const { operator } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATOR_BALANCE, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(nodeOperatorId !== undefined); + return operator.getBondBalance(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-curve-id.ts b/modules/web3/hooks/use-operator-curve-id.ts new file mode 100644 index 000000000..7eb43792c --- /dev/null +++ b/modules/web3/hooks/use-operator-curve-id.ts @@ -0,0 +1,25 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_CURVE_ID = ['operator-curve-id']; + +export const useOperatorCurveId = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: bigint) => TData, +) => { + const { operator } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATOR_CURVE_ID, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(nodeOperatorId !== undefined); + return operator.getCurveId(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-group-id.ts b/modules/web3/hooks/use-operator-group-id.ts new file mode 100644 index 000000000..354ed3c15 --- /dev/null +++ b/modules/web3/hooks/use-operator-group-id.ts @@ -0,0 +1,24 @@ +import { MODULE_NAME, NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_GROUP_ID = ['operator-group-id']; + +export const useOperatorGroupId = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + const sdk = useSmSDK(MODULE_NAME.CM); + + return useQuery({ + queryKey: [...KEY_OPERATOR_GROUP_ID, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(sdk); + invariant(nodeOperatorId !== undefined); + return sdk.metaRegistry.getOperatorGroupId(nodeOperatorId); + }, + enabled: !!sdk && nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-operator-group-stake-summary.ts b/modules/web3/hooks/use-operator-group-stake-summary.ts new file mode 100644 index 000000000..ecf9b63fa --- /dev/null +++ b/modules/web3/hooks/use-operator-group-stake-summary.ts @@ -0,0 +1,24 @@ +import { MODULE_NAME, NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_GROUP_SUMMARY = ['operator-group-summary']; + +export const useOperatorGroupStakeSummary = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + const sdk = useSmSDK(MODULE_NAME.CM); + + return useQuery({ + queryKey: [...KEY_OPERATOR_GROUP_SUMMARY, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(sdk); + invariant(nodeOperatorId !== undefined); + return sdk.metaRegistry.getOperatorGroupStakeSummary(nodeOperatorId); + }, + enabled: !!sdk && nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-operator-group.ts b/modules/web3/hooks/use-operator-group.ts new file mode 100644 index 000000000..6afaf61e3 --- /dev/null +++ b/modules/web3/hooks/use-operator-group.ts @@ -0,0 +1,24 @@ +import { MODULE_NAME, NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_GROUP = ['operator-group']; + +export const useOperatorGroup = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + const sdk = useSmSDK(MODULE_NAME.CM); + + return useQuery({ + queryKey: [...KEY_OPERATOR_GROUP, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(sdk); + invariant(nodeOperatorId !== undefined); + return sdk.metaRegistry.getOperatorGroup(nodeOperatorId); + }, + enabled: !!sdk && nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-operator-info.ts b/modules/web3/hooks/use-operator-info.ts new file mode 100644 index 000000000..fce108077 --- /dev/null +++ b/modules/web3/hooks/use-operator-info.ts @@ -0,0 +1,25 @@ +import { NodeOperatorId, NodeOperatorInfo } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_INFO = ['operator-info']; + +export const useOperatorInfo = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: NodeOperatorInfo) => TData, +) => { + const { operator } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATOR_INFO, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(nodeOperatorId !== undefined); + return await operator.getInfo(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-is-owner.ts b/modules/web3/hooks/use-operator-is-owner.ts new file mode 100644 index 000000000..3c722f23c --- /dev/null +++ b/modules/web3/hooks/use-operator-is-owner.ts @@ -0,0 +1,29 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { Address } from 'viem'; +import { useSmSDK } from '../web3-provider'; +import { useDappStatus } from './use-dapp-status'; + +export const KEY_OPERATOR_IS_OWNER = ['operator-is-owner']; + +export const useOperatorIsOwner = ( + nodeOperatorId: NodeOperatorId | undefined, + customAddress?: Address, +) => { + const { address: dappAddress } = useDappStatus(); + const address = customAddress ?? dappAddress; + const { operator } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATOR_IS_OWNER, { address, nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(address); + invariant(nodeOperatorId !== undefined); + return operator.isOwner(nodeOperatorId, address); + }, + enabled: !!address && nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-operator-keys-with-issues.ts b/modules/web3/hooks/use-operator-keys-with-issues.ts new file mode 100644 index 000000000..b6b3992d6 --- /dev/null +++ b/modules/web3/hooks/use-operator-keys-with-issues.ts @@ -0,0 +1,25 @@ +import { NodeOperatorId, ValidatorInfoIssues } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_FEE_RECIPIENT_ISSUES = ['fee-recipient-issues']; + +export const useOperatorKeysWithIssues = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: ValidatorInfoIssues[]) => TData, +) => { + const { feesMonitoring } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_FEE_RECIPIENT_ISSUES, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(nodeOperatorId !== undefined); + return feesMonitoring.getKeysWithIssues(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-keys-with-status.ts b/modules/web3/hooks/use-operator-keys-with-status.ts new file mode 100644 index 000000000..92dc5df68 --- /dev/null +++ b/modules/web3/hooks/use-operator-keys-with-status.ts @@ -0,0 +1,25 @@ +import { KeyWithStatus, NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_KEYS = ['operator-keys']; + +export const useOperatorKeysWithStatus = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: KeyWithStatus[]) => TData, +) => { + const { keysWithStatus } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATOR_KEYS, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(nodeOperatorId !== undefined); + return keysWithStatus.getKeys(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-keys-with-strikes.ts b/modules/web3/hooks/use-operator-keys-with-strikes.ts new file mode 100644 index 000000000..489a1bb95 --- /dev/null +++ b/modules/web3/hooks/use-operator-keys-with-strikes.ts @@ -0,0 +1,30 @@ +import { + KeyWithStrikes, + MODULE_NAME, + NodeOperatorId, +} from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_STRIKES = ['operator-strikes']; + +export const useOperatorKeysWithStrikes = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: KeyWithStrikes[]) => TData, +) => { + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: [...KEY_OPERATOR_STRIKES, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(sdk); + invariant(nodeOperatorId !== undefined); + return sdk.strikes.getKeysWithStrikes(nodeOperatorId); + }, + enabled: !!sdk && nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-keys-with-wrong-fee-recipient.ts b/modules/web3/hooks/use-operator-keys-with-wrong-fee-recipient.ts new file mode 100644 index 000000000..a7f4a85ea --- /dev/null +++ b/modules/web3/hooks/use-operator-keys-with-wrong-fee-recipient.ts @@ -0,0 +1,33 @@ +import { + KEY_STATUS, + NodeOperatorId, + ValidatorInfoIssues, +} from '@lidofinance/lido-csm-sdk'; +import { useCallback } from 'react'; +import { useOperatorKeysWithStatus } from './use-operator-keys-with-status'; +import { useOperatorKeysWithIssues } from './use-operator-keys-with-issues'; + +const ACTIVE_STATUSES = [KEY_STATUS.ACTIVE, KEY_STATUS.EXITING]; + +export const useOperatorKeysWithWrongFeeRecipient = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + const { data: keysWithStatus } = useOperatorKeysWithStatus(nodeOperatorId); + + const isActive = useCallback( + (data: ValidatorInfoIssues[]) => + data + .filter((issue) => issue.status === 'InvalidFeeRecipient') + .filter( + (issue) => + keysWithStatus + ?.find((key) => key.pubkey === issue.pubkey) + ?.statuses.some((status) => ACTIVE_STATUSES.includes(status)) ?? + false, + ) + .map((issue) => issue.pubkey), + [keysWithStatus], + ); + + return useOperatorKeysWithIssues(nodeOperatorId, isActive); +}; diff --git a/modules/web3/hooks/use-operator-last-rewards.ts b/modules/web3/hooks/use-operator-last-rewards.ts new file mode 100644 index 000000000..04fdf19c6 --- /dev/null +++ b/modules/web3/hooks/use-operator-last-rewards.ts @@ -0,0 +1,21 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const useOperatorLastRewards = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + const { rewards } = useSmSDK(); + + return useQuery({ + queryKey: ['operator-last-rewards', { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(nodeOperatorId !== undefined); + return rewards.getOperatorRewardsInLastReport(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-operator-metadata.ts b/modules/web3/hooks/use-operator-metadata.ts new file mode 100644 index 000000000..2c4b0fd05 --- /dev/null +++ b/modules/web3/hooks/use-operator-metadata.ts @@ -0,0 +1,31 @@ +import { + MODULE_NAME, + NodeOperatorId, + OperatorMetadata, +} from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; + +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_METADATA = ['operator-metadata']; + +export const useOperatorMetadata = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: OperatorMetadata) => TData, +) => { + const sdk = useSmSDK(MODULE_NAME.CM); + + return useQuery({ + queryKey: [...KEY_OPERATOR_METADATA, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(nodeOperatorId !== undefined); + invariant(sdk); + return await sdk.metaRegistry.getOperatorInfo(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined && !!sdk, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-owner.ts b/modules/web3/hooks/use-operator-owner.ts new file mode 100644 index 000000000..d001fcc18 --- /dev/null +++ b/modules/web3/hooks/use-operator-owner.ts @@ -0,0 +1,19 @@ +import { NodeOperatorId, ROLES } from '@lidofinance/lido-csm-sdk'; +import { useOperatorInfo } from './use-operator-info'; + +export type NodeOperatorOwner = { + role: ROLES; + address: string; +}; + +export const useOperatorOwner = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + return useOperatorInfo(nodeOperatorId, (info) => { + const isManagerOwner = info.extendedManagerPermissions; + return { + role: isManagerOwner ? ROLES.MANAGER : ROLES.REWARDS, + address: isManagerOwner ? info.managerAddress : info.rewardsAddress, + }; + }); +}; diff --git a/modules/web3/hooks/use-operator-penalties.ts b/modules/web3/hooks/use-operator-penalties.ts new file mode 100644 index 000000000..8286fec61 --- /dev/null +++ b/modules/web3/hooks/use-operator-penalties.ts @@ -0,0 +1,25 @@ +import { NodeOperatorId, PenaltyRecord } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_PENALTIES = ['operator-penalties']; + +export const useOperatorPenalties = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: PenaltyRecord[]) => TData, +) => { + const { events } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATOR_PENALTIES, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(nodeOperatorId !== undefined); + return events.getPenalties(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-reward.ts b/modules/web3/hooks/use-operator-reward.ts new file mode 100644 index 000000000..e3bdbd22f --- /dev/null +++ b/modules/web3/hooks/use-operator-reward.ts @@ -0,0 +1,23 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_REWARDS = ['operator-rewards']; + +export const useOperatorRewards = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + const { rewards } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATOR_REWARDS, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(nodeOperatorId !== undefined); + return rewards.getRewards(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-operator-rewards-history.ts b/modules/web3/hooks/use-operator-rewards-history.ts new file mode 100644 index 000000000..a2e003e06 --- /dev/null +++ b/modules/web3/hooks/use-operator-rewards-history.ts @@ -0,0 +1,28 @@ +import { + NodeOperatorId, + OperatorRewardsHistory, +} from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_REWARDS_HISTORY = ['operator-rewards-history']; + +export const useOperatorRewardsHistory = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: OperatorRewardsHistory) => TData, +) => { + const { rewards } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATOR_REWARDS_HISTORY, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(nodeOperatorId !== undefined); + return rewards.getOperatorRewardsHistory(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-short-info.ts b/modules/web3/hooks/use-operator-short-info.ts new file mode 100644 index 000000000..31156c350 --- /dev/null +++ b/modules/web3/hooks/use-operator-short-info.ts @@ -0,0 +1,27 @@ +import { + NodeOperatorId, + NodeOperatorShortInfo, +} from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; +import { KEY_OPERATOR_INFO } from './use-operator-info'; + +export const useOperatorShortInfo = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: NodeOperatorShortInfo) => TData, +) => { + const { operator } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATOR_INFO, 'short', { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(nodeOperatorId !== undefined); + return await operator.getManagementProperties(nodeOperatorId); + }, + enabled: nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-stake-summary.ts b/modules/web3/hooks/use-operator-stake-summary.ts new file mode 100644 index 000000000..b008e4952 --- /dev/null +++ b/modules/web3/hooks/use-operator-stake-summary.ts @@ -0,0 +1,31 @@ +import { + MODULE_NAME, + NodeOperatorId, + OperatorStakeSummary, +} from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_STAKE_INFO = ['operator-stake-info']; + +export const useOperatorStakeSummary = ( + nodeOperatorId: NodeOperatorId | undefined, + select?: (data: OperatorStakeSummary) => TData, +) => { + const sdk = useSmSDK(MODULE_NAME.CM); + + return useQuery({ + queryKey: [...KEY_OPERATOR_STAKE_INFO, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(sdk); + invariant(nodeOperatorId !== undefined); + + return sdk.metaRegistry.getOperatorStakeSummary(nodeOperatorId); + }, + enabled: !!sdk && nodeOperatorId !== undefined, + select, + }); +}; diff --git a/modules/web3/hooks/use-operator-type.ts b/modules/web3/hooks/use-operator-type.ts new file mode 100644 index 000000000..3b2b0d600 --- /dev/null +++ b/modules/web3/hooks/use-operator-type.ts @@ -0,0 +1,8 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useModuleOperatorTypeGetter } from 'shared/hooks'; +import { useOperatorCurveId } from './use-operator-curve-id'; + +export const useOperatorType = (id: NodeOperatorId | undefined) => { + const getOperatorType = useModuleOperatorTypeGetter(); + return useOperatorCurveId(id, getOperatorType); +}; diff --git a/modules/web3/hooks/use-operator-weight.ts b/modules/web3/hooks/use-operator-weight.ts new file mode 100644 index 000000000..77fce0492 --- /dev/null +++ b/modules/web3/hooks/use-operator-weight.ts @@ -0,0 +1,24 @@ +import { MODULE_NAME, NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import invariant from 'tiny-invariant'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATOR_WEIGHT = ['operator-weight']; + +export const useOperatorWeight = ( + nodeOperatorId: NodeOperatorId | undefined, +) => { + const sdk = useSmSDK(MODULE_NAME.CM); + + return useQuery({ + queryKey: [...KEY_OPERATOR_WEIGHT, { nodeOperatorId }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(sdk); + invariant(nodeOperatorId !== undefined); + return sdk.metaRegistry.getOperatorWeight(nodeOperatorId); + }, + enabled: !!sdk && nodeOperatorId !== undefined, + }); +}; diff --git a/modules/web3/hooks/use-operators-count.ts b/modules/web3/hooks/use-operators-count.ts new file mode 100644 index 000000000..2a6a84375 --- /dev/null +++ b/modules/web3/hooks/use-operators-count.ts @@ -0,0 +1,13 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useSmSDK } from '../web3-provider'; + +export const useOperatorsCount = () => { + const { module } = useSmSDK(); + + return useQuery({ + queryKey: ['operators-count'], + ...STRATEGY_CONSTANT, + queryFn: () => module.getOperatorsCount(), + }); +}; diff --git a/modules/web3/hooks/use-operators-with-locked-bond.ts b/modules/web3/hooks/use-operators-with-locked-bond.ts new file mode 100644 index 000000000..f7b4aa899 --- /dev/null +++ b/modules/web3/hooks/use-operators-with-locked-bond.ts @@ -0,0 +1,18 @@ +import { STETH_ROUNDING_THRESHOLD } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useSmSDK } from '../web3-provider'; + +export const KEY_OPERATORS_WITH_LOCKED_BOND = ['operators-with-locked-bond']; + +export const useOperatorsWithLockedBond = () => { + const { delayedPenalty } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_OPERATORS_WITH_LOCKED_BOND], + ...STRATEGY_CONSTANT, + queryFn: () => delayedPenalty.getOperatorsWithLockedBond(), + select: (data) => + data.filter(({ locked }) => locked > STETH_ROUNDING_THRESHOLD), + }); +}; diff --git a/modules/web3/hooks/use-other-module.ts b/modules/web3/hooks/use-other-module.ts new file mode 100644 index 000000000..84c89b90e --- /dev/null +++ b/modules/web3/hooks/use-other-module.ts @@ -0,0 +1,21 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useDappStatus, useSmSDK } from 'modules/web3'; +import invariant from 'tiny-invariant'; +import { Address } from 'viem'; + +export const useOtherModule = (customAddress?: Address) => { + const { address: dappAddress } = useDappStatus(); + const address = customAddress ?? dappAddress; + const { module } = useSmSDK(); + + return useQuery({ + queryKey: ['other-module', { address }], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(address); + return module.getUsedOtherModule(address); + }, + enabled: !!address, + }); +}; diff --git a/modules/web3/hooks/use-share-limit-percentage.ts b/modules/web3/hooks/use-share-limit-percentage.ts new file mode 100644 index 000000000..8678d75d0 --- /dev/null +++ b/modules/web3/hooks/use-share-limit-percentage.ts @@ -0,0 +1,5 @@ +import { useShareLimit } from './use-share-limit'; + +export const useShareLimitPercentage = () => { + return useShareLimit((data) => data.shareLimit); +}; diff --git a/modules/web3/hooks/use-share-limit-status.ts b/modules/web3/hooks/use-share-limit-status.ts new file mode 100644 index 000000000..88dd5cfb9 --- /dev/null +++ b/modules/web3/hooks/use-share-limit-status.ts @@ -0,0 +1,22 @@ +import { useShareLimit } from './use-share-limit'; + +export const SHARE_LIMIT_STATUS = { + FAR: 'FAR', + APPROACHING: 'APPROACHING', + EXHAUSTED: 'EXHAUSTED', + REACHED: 'REACHED', +} as const; + +export const SHARE_LIMIT_APPROACHING_THRESHOLD = 200n; + +export const useShareLimitStatus = () => { + return useShareLimit((data) => + data.activeLeft <= 0 + ? SHARE_LIMIT_STATUS.REACHED + : data.activeLeft - data.queue < 0 + ? SHARE_LIMIT_STATUS.EXHAUSTED + : data.activeLeft - data.queue < SHARE_LIMIT_APPROACHING_THRESHOLD + ? SHARE_LIMIT_STATUS.APPROACHING + : SHARE_LIMIT_STATUS.FAR, + ); +}; diff --git a/modules/web3/hooks/use-share-limit.ts b/modules/web3/hooks/use-share-limit.ts new file mode 100644 index 000000000..2a7e7e8e9 --- /dev/null +++ b/modules/web3/hooks/use-share-limit.ts @@ -0,0 +1,24 @@ +import { MODULE_NAME, ShareLimitInfo } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useSmSDK } from 'modules/web3'; +import invariant from 'tiny-invariant'; + +export const KEY_SHARE_LIMIT = ['share-limit']; + +export const useShareLimit = ( + select?: (data: ShareLimitInfo) => TData, +) => { + const sdk = useSmSDK(MODULE_NAME.CSM); + + return useQuery({ + queryKey: [...KEY_SHARE_LIMIT], + ...STRATEGY_CONSTANT, + queryFn: () => { + invariant(sdk); + return sdk.module.getShareLimit(); + }, + select, + enabled: !!sdk, + }); +}; diff --git a/modules/web3/hooks/use-sm-status.ts b/modules/web3/hooks/use-sm-status.ts new file mode 100644 index 000000000..2c0c53391 --- /dev/null +++ b/modules/web3/hooks/use-sm-status.ts @@ -0,0 +1,27 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useSmSDK } from '../web3-provider'; + +export const useSmStatus = () => { + const { module } = useSmSDK(); + + return useQuery({ + queryKey: ['sm-status'], + ...STRATEGY_CONSTANT, + queryFn: () => module.getStatus(), + select: (data) => ({ + ...data, + isPaused: data.isPausedAccounting || data.isPausedModule, + }), + }); +}; + +export const useSmVersionSupported = () => { + const { module } = useSmSDK(); + + return useQuery({ + queryKey: ['sm-version'], + ...STRATEGY_CONSTANT, + queryFn: async () => module.isVersionsSupported(), + }); +}; diff --git a/modules/web3/hooks/use-stETH-by-wstETH.ts b/modules/web3/hooks/use-stETH-by-wstETH.ts new file mode 100644 index 000000000..13542e396 --- /dev/null +++ b/modules/web3/hooks/use-stETH-by-wstETH.ts @@ -0,0 +1,20 @@ +import { useQuery } from '@tanstack/react-query'; +import { useLidoSDK } from 'modules/web3'; +import invariant from 'tiny-invariant'; + +// FIXME: use lido-csm-sdk +export const useStETHByWstETH = (wsteth: bigint | undefined | null) => { + const { wrap } = useLidoSDK(); + + return useQuery({ + queryKey: ['steth-by-wsteth', wsteth], + enabled: wsteth != null && !!wrap, + staleTime: Infinity, + queryFn: () => { + if (wsteth === 0n) return 0n; + invariant(wsteth); + + return wrap.convertWstethToSteth(wsteth); + }, + }); +}; diff --git a/modules/web3/hooks/use-stake-limit.ts b/modules/web3/hooks/use-stake-limit.ts new file mode 100644 index 000000000..3cafc2483 --- /dev/null +++ b/modules/web3/hooks/use-stake-limit.ts @@ -0,0 +1,16 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useLidoSDK } from 'modules/web3'; + +export const KEY_STAKE_LIMIT = ['stake-limit']; + +export const useStakeLimit = () => { + const { stake } = useLidoSDK(); + + return useQuery({ + queryKey: KEY_STAKE_LIMIT, + ...STRATEGY_CONSTANT, + queryFn: () => stake.getStakeLimitInfo(), + select: (data) => (data.isStakingPaused ? 0n : data.currentStakeLimit), + }); +}; diff --git a/modules/web3/hooks/use-steth-pool-data.ts b/modules/web3/hooks/use-steth-pool-data.ts new file mode 100644 index 000000000..8c394c381 --- /dev/null +++ b/modules/web3/hooks/use-steth-pool-data.ts @@ -0,0 +1,19 @@ +import { StethPoolData } from '@lidofinance/lido-csm-sdk'; +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useSmSDK } from 'modules/web3'; + +export const KEY_STETH_POOL_DATA = ['steth-pool-data']; + +export const useStethPoolData = ( + select?: (data: StethPoolData) => TData, +) => { + const { accounting } = useSmSDK(); + + return useQuery({ + queryKey: [...KEY_STETH_POOL_DATA], + ...STRATEGY_CONSTANT, + queryFn: () => accounting.getStethPoolData(), + select, + }); +}; diff --git a/modules/web3/hooks/use-tx-confirmation.ts b/modules/web3/hooks/use-tx-confirmation.ts new file mode 100644 index 000000000..838f54b14 --- /dev/null +++ b/modules/web3/hooks/use-tx-confirmation.ts @@ -0,0 +1,22 @@ +import { useCallback } from 'react'; +import type { Hash } from 'viem'; +import { waitForTransactionReceipt } from 'viem/actions'; +import { useClient } from 'wagmi'; +import { useDappStatus } from 'modules/web3'; + +// helper hook until migration to wagmi is complete +// awaits TX trough wagmi transport to allow sync with balance hooks +export const useTxConfirmation = () => { + const { chainId } = useDappStatus(); + const client = useClient({ chainId }); + + return useCallback( + (hash: string) => { + return waitForTransactionReceipt(client as any, { + confirmations: 1, + hash: hash as Hash, + }); + }, + [client], + ); +}; diff --git a/modules/web3/hooks/use-wstETH-by-stETH.ts b/modules/web3/hooks/use-wstETH-by-stETH.ts new file mode 100644 index 000000000..f49081338 --- /dev/null +++ b/modules/web3/hooks/use-wstETH-by-stETH.ts @@ -0,0 +1,20 @@ +import invariant from 'tiny-invariant'; +import { useQuery } from '@tanstack/react-query'; +import { useLidoSDK } from 'modules/web3'; + +// FIXME: use lido-csm-sdk +export const useWstethBySteth = (steth: bigint | undefined | null) => { + const { wrap } = useLidoSDK(); + + return useQuery({ + queryKey: ['wsteth-by-steth', steth], + enabled: steth != null && !!wrap, + staleTime: Infinity, + queryFn: () => { + if (steth === 0n) return 0n; + invariant(steth); + + return wrap.convertStethToWsteth(steth); + }, + }); +}; diff --git a/modules/web3/index.ts b/modules/web3/index.ts new file mode 100644 index 000000000..1500ce25a --- /dev/null +++ b/modules/web3/index.ts @@ -0,0 +1,4 @@ +export * from './hooks'; +export * from './utils'; +export * from './web3-provider'; +export * from './operator-provider'; diff --git a/modules/web3/operator-provider/index.ts b/modules/web3/operator-provider/index.ts new file mode 100644 index 000000000..e8b1f904d --- /dev/null +++ b/modules/web3/operator-provider/index.ts @@ -0,0 +1,3 @@ +export * from './node-operator-provider'; +export * from './use-available-operators'; +export * from './use-append-operator'; diff --git a/modules/web3/operator-provider/node-operator-provider.tsx b/modules/web3/operator-provider/node-operator-provider.tsx new file mode 100644 index 000000000..3363c1634 --- /dev/null +++ b/modules/web3/operator-provider/node-operator-provider.tsx @@ -0,0 +1,78 @@ +import { + NodeOperatorId, + NodeOperatorShortInfo, +} from '@lidofinance/lido-csm-sdk'; +import { + createContext, + FC, + PropsWithChildren, + useCallback, + useContext, + useMemo, +} from 'react'; +import invariant from 'tiny-invariant'; +import { useActiveNodeOperator } from './use-active-node-operator'; +import { useAvailableOperators } from './use-available-operators'; + +export type NodeOperatorContextValue = { + isPending: boolean; + nodeOperator: NodeOperatorShortInfo | undefined; + switchNodeOperator: (id: NodeOperatorId) => void; +}; + +export type NodeOperatorDefinedContextValue = NodeOperatorContextValue & { + nodeOperator: NodeOperatorShortInfo; +}; + +export const NodeOperatorContext = + createContext(null); + +export const useNodeOperator = < + TDefined extends boolean = false, +>(): TDefined extends true + ? NodeOperatorDefinedContextValue + : NodeOperatorContextValue => { + const value = useContext(NodeOperatorContext); + invariant( + value, + 'useNodeOperator was used outside the NodeOperatorContext provider', + ); + return value as any; +}; + +export const useNodeOperatorId = < + TDefined extends boolean = false, +>(): TDefined extends true ? NodeOperatorId : NodeOperatorId | undefined => { + const value = useContext(NodeOperatorContext); + invariant( + value, + 'useNodeOperatorId was used outside the NodeOperatorContext provider', + ); + return value.nodeOperator?.nodeOperatorId as any; +}; + +export const NodeOperatorProvider: FC = ({ children }) => { + const { data: list, isPending } = useAvailableOperators(); + const [active, setActive] = useActiveNodeOperator(list); + + const switchNodeOperator = useCallback( + (id: NodeOperatorId) => { + const newActive = list?.find((item) => item.nodeOperatorId === id); + if (newActive) { + setActive(newActive); + } + }, + [list, setActive], + ); + + const value = useMemo( + () => ({ isPending, nodeOperator: active, switchNodeOperator }), + [active, isPending, switchNodeOperator], + ); + + return ( + + {children} + + ); +}; diff --git a/modules/web3/operator-provider/use-active-node-operator.ts b/modules/web3/operator-provider/use-active-node-operator.ts new file mode 100644 index 000000000..0099bce85 --- /dev/null +++ b/modules/web3/operator-provider/use-active-node-operator.ts @@ -0,0 +1,42 @@ +import { NodeOperatorShortInfo } from '@lidofinance/lido-csm-sdk'; +import { useEffect, useRef, useState } from 'react'; +import { useDappStatus } from '../hooks'; +import { useCachedId } from './use-cached-id'; +import { useInvalidateOperatorCache } from './use-invalidate-operator-cache'; + +export const useActiveNodeOperator = (list?: NodeOperatorShortInfo[]) => { + const [active, setActive] = useState(); + const [, setCachedId] = useCachedId(); + const { address } = useDappStatus(); + const invalidate = useInvalidateOperatorCache(); + + const resolved = active ?? list?.[0]; + + const prevActiveRef = useRef(resolved); + const prevAddressRef = useRef(address); + + if (address !== prevAddressRef.current) { + prevAddressRef.current = address; + prevActiveRef.current = resolved; + invalidate('operatorAndAddress'); + } else if (resolved !== prevActiveRef.current) { + prevActiveRef.current = resolved; + invalidate('operator'); + } + + useEffect(() => { + setActive((prev) => { + const updated = list?.find( + (item) => item.nodeOperatorId === prev?.nodeOperatorId, + ); + + return updated ?? list?.[0]; + }); + }, [list]); + + useEffect(() => { + resolved && setCachedId(resolved.nodeOperatorId); + }, [resolved, setCachedId]); + + return [resolved, setActive] as const; +}; diff --git a/modules/web3/operator-provider/use-append-operator.ts b/modules/web3/operator-provider/use-append-operator.ts new file mode 100644 index 000000000..2783f4769 --- /dev/null +++ b/modules/web3/operator-provider/use-append-operator.ts @@ -0,0 +1,40 @@ +import { + appendNodeOperator, + NodeOperatorId, + NodeOperatorShortInfo, +} from '@lidofinance/lido-csm-sdk'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { useEffect, useRef } from 'react'; +import { useDappStatus } from '../hooks'; +import { useNodeOperator } from './node-operator-provider'; +import { KEY_OPERATORS } from './use-available-operators'; + +export const useAppendOperator = (switchOperator?: boolean) => { + const queryClient = useQueryClient(); + const { address } = useDappStatus(); + const { switchNodeOperator } = useNodeOperator(); + const pendingSwitchRef = useRef(); + + // Deferred switch: fires after React re-renders with updated operator list + useEffect(() => { + if (pendingSwitchRef.current !== undefined) { + switchNodeOperator(pendingSwitchRef.current); + pendingSwitchRef.current = undefined; + } + }, [switchNodeOperator]); + + const { mutate } = useMutation({ + mutationFn: async (value: NodeOperatorShortInfo) => value, + onSuccess: (data) => { + queryClient.setQueryData( + [...KEY_OPERATORS, { address }], + (prev = []) => appendNodeOperator(prev, data), + ); + if (switchOperator) { + pendingSwitchRef.current = data.nodeOperatorId; + } + }, + }); + + return mutate; +}; diff --git a/modules/web3/operator-provider/use-available-operators.ts b/modules/web3/operator-provider/use-available-operators.ts new file mode 100644 index 000000000..874478246 --- /dev/null +++ b/modules/web3/operator-provider/use-available-operators.ts @@ -0,0 +1,31 @@ +import { useQuery } from '@tanstack/react-query'; +import { STRATEGY_CONSTANT } from 'consts'; +import { useMemo } from 'react'; +import invariant from 'tiny-invariant'; +import { useDappStatus } from '../hooks'; +import { useSmSDK } from '../web3-provider'; +import { useCachedNodeOperator } from './use-cached-node-operator'; + +export const KEY_OPERATORS = ['node-operators']; + +export const useAvailableOperators = () => { + const { discovery } = useSmSDK(); + const { address } = useDappStatus(); + + const { data: cached } = useCachedNodeOperator(); + const placeholderData = useMemo( + () => (cached ? [cached] : undefined), + [cached], + ); + + return useQuery({ + queryKey: [...KEY_OPERATORS, { address }], + ...STRATEGY_CONSTANT, + queryFn: async () => { + invariant(address); + return discovery.getNodeOperatorsByAddress(address); + }, + enabled: !!address, + placeholderData, + }); +}; diff --git a/modules/web3/operator-provider/use-cached-id.ts b/modules/web3/operator-provider/use-cached-id.ts new file mode 100644 index 000000000..2a3e1b5cd --- /dev/null +++ b/modules/web3/operator-provider/use-cached-id.ts @@ -0,0 +1,17 @@ +import { NodeOperatorId } from '@lidofinance/lido-csm-sdk'; +import { useLocalStorage } from 'shared/hooks'; +import { useDappStatus } from '../hooks'; +import { useSmSDK } from '../web3-provider'; + +export const useCachedId = () => { + const { address } = useDappStatus(); + const { + core: { moduleId }, + } = useSmSDK(); + + return useLocalStorage( + address ? `sm-${moduleId}-no-${address}` : undefined, + undefined, + BigInt, + ); +}; diff --git a/modules/web3/operator-provider/use-cached-node-operator.ts b/modules/web3/operator-provider/use-cached-node-operator.ts new file mode 100644 index 000000000..fbaa22f70 --- /dev/null +++ b/modules/web3/operator-provider/use-cached-node-operator.ts @@ -0,0 +1,29 @@ +import { + getNodeOperatorRoles, + NodeOperatorShortInfo, +} from '@lidofinance/lido-csm-sdk'; +import { useCallback } from 'react'; +import { useDappStatus, useOperatorShortInfo } from '../hooks'; +import { useCachedId } from './use-cached-id'; + +export const useCachedNodeOperator = () => { + const { address } = useDappStatus(); + const [cachedId, setCachedId] = useCachedId(); + + const select = useCallback( + (data: NodeOperatorShortInfo) => { + if (!cachedId || !address) return undefined; + const roles = getNodeOperatorRoles(data, address); + + if (roles.length === 0) { + setCachedId(undefined); + return undefined; + } + + return data; + }, + [address, cachedId, setCachedId], + ); + + return useOperatorShortInfo(cachedId, select); +}; diff --git a/modules/web3/operator-provider/use-invalidate-operator-cache.ts b/modules/web3/operator-provider/use-invalidate-operator-cache.ts new file mode 100644 index 000000000..8db2e4326 --- /dev/null +++ b/modules/web3/operator-provider/use-invalidate-operator-cache.ts @@ -0,0 +1,26 @@ +import { useQueryClient } from '@tanstack/react-query'; +import { useSmSDK } from 'modules/web3/web3-provider'; +import { useCallback } from 'react'; + +type InvalidationScope = 'operator' | 'address' | 'operatorAndAddress'; + +export const useInvalidateOperatorCache = () => { + const queryClient = useQueryClient(); + const sdk = useSmSDK(); + + return useCallback( + (scope: InvalidationScope = 'operatorAndAddress') => { + sdk.core.invalidateCache(); + void queryClient.invalidateQueries({ + predicate: (query) => + query.queryKey.some((part) => { + if (typeof part !== 'object' || part === null) return false; + if (scope === 'operator') return 'nodeOperatorId' in part; + if (scope === 'address') return 'address' in part; + return 'operator' in part || 'nodeOperatorId' in part; + }), + }); + }, + [sdk.core, queryClient], + ); +}; diff --git a/modules/web3/utils/apply-round-up-gas-limit.ts b/modules/web3/utils/apply-round-up-gas-limit.ts new file mode 100644 index 000000000..8fe57aab6 --- /dev/null +++ b/modules/web3/utils/apply-round-up-gas-limit.ts @@ -0,0 +1,3 @@ +export const applyRoundUpGasLimit = (number: bigint): bigint => + // 94567 -> 94 -> 94000 -> 94999 + (number / 1_000n) * 1_000n + 999n; diff --git a/modules/web3/utils/get-max-balance-token.ts b/modules/web3/utils/get-max-balance-token.ts new file mode 100644 index 000000000..2dd4c2ab2 --- /dev/null +++ b/modules/web3/utils/get-max-balance-token.ts @@ -0,0 +1,21 @@ +import { PerToken, TOKENS } from '@lidofinance/lido-csm-sdk'; + +type Props = Partial>; + +// TODO: convert wsteth amount + +export const getMaxBalanceToken = (props: Props): TOKENS => { + const balances = [ + { token: TOKENS.steth, balance: props.stETH ?? 0n }, + { token: TOKENS.wsteth, balance: props.wstETH ?? 0n }, + { token: TOKENS.eth, balance: props.ETH ?? 0n }, + ]; + + return balances.reduce( + (max, current) => (max.balance >= current.balance ? max : current), + { + balance: 0n, + token: TOKENS.steth, + }, + ).token; +}; diff --git a/modules/web3/utils/index.ts b/modules/web3/utils/index.ts new file mode 100644 index 000000000..abf8b49f7 --- /dev/null +++ b/modules/web3/utils/index.ts @@ -0,0 +1,2 @@ +export * from './apply-round-up-gas-limit'; +export * from './get-max-balance-token'; diff --git a/modules/web3/web3-provider/devnet.ts b/modules/web3/web3-provider/devnet.ts new file mode 100644 index 000000000..795795b3f --- /dev/null +++ b/modules/web3/web3-provider/devnet.ts @@ -0,0 +1,55 @@ +import { Address, isAddress } from 'viem'; + +import { CONTRACT_NAMES, CURATED_GATES } from '@lidofinance/lido-csm-sdk'; +import { config } from 'config'; + +type DevnetJson = Record; + +// Map JSON keys from deployment artifacts to SDK contract names +const ADDRESS_MAP: Record = { + Accounting: CONTRACT_NAMES.accounting, + CSModule: CONTRACT_NAMES.csModule, + CuratedModule: CONTRACT_NAMES.curatedModule, + Ejector: CONTRACT_NAMES.ejector, + ExitPenalties: CONTRACT_NAMES.exitPenalties, + FeeDistributor: CONTRACT_NAMES.feeDistributor, + FeeOracle: CONTRACT_NAMES.feeOracle, + HashConsensus: CONTRACT_NAMES.hashConsensus, + ParametersRegistry: CONTRACT_NAMES.parametersRegistry, + ValidatorStrikes: CONTRACT_NAMES.validatorStrikes, + Verifier: CONTRACT_NAMES.verifier, + MetaRegistry: CONTRACT_NAMES.metaRegistry, + PermissionlessGate: CONTRACT_NAMES.permissionlessGate, + VettedGate: CONTRACT_NAMES.icsGate, + IdentifiedDVTClusterGate: CONTRACT_NAMES.idvtcGate, +}; + +export const parseDevnetAddresses = ( + json: DevnetJson, +): Partial> => { + const result: Partial> = {}; + + for (const [jsonKey, sdkKey] of Object.entries(ADDRESS_MAP)) { + const value = json[jsonKey]; + if (typeof value === 'string' && value.startsWith('0x')) { + result[sdkKey] = value as Address; + } + } + + // Handle CuratedGates array → curatedGate1..9 + const gates = json.CuratedGates; + if (Array.isArray(gates)) { + CURATED_GATES.forEach((contractName, index) => { + const address = gates[index]; + if (address && isAddress(address)) { + result[contractName] = address; + } + }); + } + + return result; +}; + +export const overridedAddresses = config.devnetAddresses + ? parseDevnetAddresses(config.devnetAddresses) + : undefined; diff --git a/modules/web3/web3-provider/index.ts b/modules/web3/web3-provider/index.ts new file mode 100644 index 000000000..87b8f90a6 --- /dev/null +++ b/modules/web3/web3-provider/index.ts @@ -0,0 +1,2 @@ +export { Web3Provider } from './web3-provider'; +export { useLidoSDK, useSmSDK } from './lido-sdk'; diff --git a/modules/web3/web3-provider/lido-sdk.tsx b/modules/web3/web3-provider/lido-sdk.tsx new file mode 100644 index 000000000..fd8d95285 --- /dev/null +++ b/modules/web3/web3-provider/lido-sdk.tsx @@ -0,0 +1,149 @@ +import { createContext, useContext, useEffect, useMemo } from 'react'; +import invariant from 'tiny-invariant'; +import { + useConnection, + useConfig, + usePublicClient, + useSwitchChain, + useWalletClient, +} from 'wagmi'; + +import { + LidoSDKCm, + LidoSDKCsm, + MODULE_NAME, + SdkProps, +} from '@lidofinance/lido-csm-sdk'; +import { + LidoSDKStake, + LidoSDKWithdraw, + LidoSDKWrap, +} from '@lidofinance/lido-ethereum-sdk'; +import { CHAINS, LidoSDKCore } from '@lidofinance/lido-ethereum-sdk/core'; +import { + LidoSDKstETH, + LidoSDKwstETH, +} from '@lidofinance/lido-ethereum-sdk/erc20'; + +import { config } from 'config'; +import { useClApiUrl } from 'config/rpc/cl'; +import { useUserConfig } from 'config/user-config'; +import { isModuleCSM } from 'consts'; + +import { overridedAddresses } from './devnet'; + +type LidoSDKContextValue = { + chainId: CHAINS; + core: LidoSDKCore; + stake: LidoSDKStake; + stETH: LidoSDKstETH; + wstETH: LidoSDKwstETH; + wrap: LidoSDKWrap; + withdraw: LidoSDKWithdraw; + sm: LidoSDKCsm | LidoSDKCm; +}; + +const chainId = config.defaultChain; + +const LidoSDKContext = createContext(null); +LidoSDKContext.displayName = 'LidoSDKContext'; + +export const useLidoSDK = () => { + const value = useContext(LidoSDKContext); + invariant(value, 'useLidoSDK was used outside of LidoSDKProvider'); + return value; +}; + +export function useSmSDK(): LidoSDKCsm | LidoSDKCm; +export function useSmSDK(module: MODULE_NAME.CSM): LidoSDKCsm | undefined; +export function useSmSDK(module: MODULE_NAME.CM): LidoSDKCm | undefined; +// eslint-disable-next-line func-style +export function useSmSDK(module?: MODULE_NAME) { + const { sm } = useLidoSDK(); + if (module && module !== config.module) { + return undefined; + } + return sm; +} + +export const LidoSDKProvider = ({ children }: React.PropsWithChildren) => { + const { data: walletClient } = useWalletClient({ chainId }); + const publicClient = usePublicClient({ chainId }); + // reset internal wagmi state after disconnect + const { isConnected } = useConnection(); + + const clApiUrl = useClApiUrl(); + const { + savedUserConfig: { ipfsGateways: userIpfsGateways }, + defaultIpfsGateways, + } = useUserConfig(); + const ipfsGateways = + userIpfsGateways.length > 0 ? userIpfsGateways : defaultIpfsGateways; + + const wagmiConfig = useConfig(); + const { mutate: switchChain } = useSwitchChain(); + useEffect(() => { + if (isConnected) { + return () => { + // protecs from side effect double run + if (!wagmiConfig.state.current) { + switchChain({ + chainId: config.defaultChain, + }); + } + }; + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isConnected]); + + const contextValue = useMemo(() => { + const core = new LidoSDKCore( + // @ts-expect-error: typing (viem + LidoSDK) + { + chainId, + // logMode: 'debug', + rpcProvider: publicClient, + web3Provider: walletClient, + }, + 'CSM', + ); + + const stake = new LidoSDKStake({ core }); + const stETH = new LidoSDKstETH({ core }); + const wstETH = new LidoSDKwstETH({ core }); + const wrap = new LidoSDKWrap({ core }); + const withdraw = new LidoSDKWithdraw({ core }); + + const smProps: SdkProps = { + core, + clApiUrl, + maxEventBlocksRange: + chainId === CHAINS.Mainnet + ? undefined + : config.MAX_BLOCK_RANGE_FOR_EVENTS, + skipHistoricalCalls: chainId !== CHAINS.Mainnet, + keysApiUrl: config.keysApiUrl, + feesMonitoringApiUrl: config.feesMonitoringApiUrl, + ipfsGateways: ipfsGateways, + overridedAddresses, + }; + + const sm = isModuleCSM ? new LidoSDKCsm(smProps) : new LidoSDKCm(smProps); + + return { + chainId: core.chainId, + core, + stake, + stETH, + wstETH, + wrap, + withdraw, + sm, + }; + }, [clApiUrl, ipfsGateways, publicClient, walletClient]); + return ( + + {children} + + ); +}; diff --git a/modules/web3/web3-provider/use-web3-transport.ts b/modules/web3/web3-provider/use-web3-transport.ts new file mode 100644 index 000000000..484f6c987 --- /dev/null +++ b/modules/web3/web3-provider/use-web3-transport.ts @@ -0,0 +1,118 @@ +import { config } from 'config'; +import { useMemo } from 'react'; +import { + type Transport, + fallback, + createTransport, + http, + Chain, + UnsupportedProviderMethodError, + InvalidParamsRpcError, +} from 'viem'; + +import type { OnResponseFn } from 'viem/_types/clients/transports/fallback'; + +// We disable those methods so wagmi uses getLogs instead to watch events +// Filters are not suitable for public rpc and break when changing between fallbacks +const DISABLED_METHODS = new Set([ + 'eth_newFilter', + 'eth_getFilterChanges', + 'eth_uninstallFilter', +]); + +// Viem fallback transport wrapped with project-wide request guards +const guardedFallbackTransport = (mainTransports: Transport[]): Transport => { + return (params) => { + const defaultTransport = fallback(mainTransports)(params); + let externalOnResponse: OnResponseFn; + + const onResponse: OnResponseFn = (response) => { + if (response.status === 'error' && !(response as any).skipLog) { + console.warn('[guardedFallbackTransport] transport error', response); + } + externalOnResponse?.(response); + }; + + return createTransport( + { + key: 'GuardedFallbackTransport', + name: 'GuardedFallbackTransport', + //@ts-expect-error invalid typings + async request(requestParams, options) { + if (DISABLED_METHODS.has(requestParams.method)) { + const error = new UnsupportedProviderMethodError( + new Error(`Method ${requestParams.method} is not supported`), + ); + onResponse({ + error, + method: requestParams.method, + params: params as unknown[], + transport: defaultTransport, + status: 'error', + // skip logging because we expect wagmi to try those + skipLog: true, + } as any); + throw error; + } + + if ( + requestParams.method === 'eth_getLogs' && + Array.isArray(requestParams?.params) && + // works for empty array, empty string and all falsish values + !requestParams.params[0]?.address?.length + ) { + const error = new InvalidParamsRpcError( + new Error(`Empty address for eth_getLogs is not supported`), + ); + onResponse({ + error, + method: requestParams.method, + params: params as unknown[], + transport: defaultTransport, + status: 'error', + }); + throw error; + } + + defaultTransport.value?.onResponse(onResponse); + return defaultTransport.request(requestParams, options); + }, + // crucial cause we quack like a fallback transport and some connectors(WC) rely on this + type: 'fallback', + }, + // transport.value contents + { + // this is fallbackTransport specific field, used by WC connectors to extract rpc Urls + transports: defaultTransport.value?.transports, + // providers that use this transport, use this to set onResponse callback for transport, + onResponse: (fn: OnResponseFn) => (externalOnResponse = fn), + }, + ); + }; +}; + +// returns Viem transport map backed by the project's backend RPC +export const useWeb3Transport = ( + supportedChains: Chain[], + backendRpcMap: Record, +) => { + return useMemo(() => { + const batchConfig = { + wait: config.PROVIDER_BATCH_TIME, + batchSize: config.PROVIDER_MAX_BATCH, + }; + + return supportedChains.reduce( + (transportMap, chain) => { + transportMap[chain.id] = guardedFallbackTransport([ + http(backendRpcMap[chain.id], { + batch: batchConfig, + name: backendRpcMap[chain.id], + }), + ]); + return transportMap; + }, + {} as Record, + ); + }, [backendRpcMap, supportedChains]); +}; diff --git a/modules/web3/web3-provider/web3-provider.tsx b/modules/web3/web3-provider/web3-provider.tsx new file mode 100644 index 000000000..6d6396416 --- /dev/null +++ b/modules/web3/web3-provider/web3-provider.tsx @@ -0,0 +1,178 @@ +import { + createContext, + FC, + PropsWithChildren, + useContext, + useMemo, +} from 'react'; +import { + Config, + WagmiProvider, + createConfig, + fallback, + usePublicClient, +} from 'wagmi'; +import * as wagmiChains from 'wagmi/chains'; + +import { + ReefKnotWalletsModal, + getDefaultWalletsModalConfig, +} from 'reef-knot/connect-wallet-modal'; +import { ReefKnotProvider, getDefaultConfig } from 'reef-knot/core-react'; +import { WalletIdsEthereum, WalletsListEthereum } from 'reef-knot/wallets'; + +import { useThemeToggle } from '@lidofinance/lido-ui'; + +import { config } from 'config'; +import { useGetRpcUrlByChainId } from 'config/rpc'; +import { useUserConfig } from 'config/user-config'; +import { walletMetricProps } from 'consts/matomo-wallets-events'; + +import { useWeb3Transport } from './use-web3-transport'; +import { LidoSDKProvider } from './lido-sdk'; +import { http, PublicClient } from 'viem'; +import invariant from 'tiny-invariant'; +import { CHAINS } from '@lidofinance/lido-ethereum-sdk'; + +type ChainsList = [wagmiChains.Chain, ...wagmiChains.Chain[]]; + +const WALLETS_PINNED: WalletIdsEthereum[] = [ + 'browserExtension', + 'walletConnect', +]; + +export const wagmiChainMap = Object.values(wagmiChains).reduce( + (acc, chain) => { + acc[chain.id] = chain; + return acc; + }, + {} as Record, +); + +type Web3ProviderContextValue = { + mainnetConfig: Config; + publicClientMainnet: PublicClient; +}; + +const Web3ProviderContext = createContext( + null, +); +Web3ProviderContext.displayName = 'Web3ProviderContext'; + +export const useMainnetOnlyWagmi = () => { + const value = useContext(Web3ProviderContext); + invariant(value, 'useMainnetOnlyWagmi was used outside of Web3Provider'); + return value; +}; + +export const Web3Provider: FC = ({ children }) => { + const { + defaultChain: defaultChainId, + walletconnectProjectId, + isWalletConnectionAllowed, + } = useUserConfig(); + const { themeName } = useThemeToggle(); + + const { supportedChains, defaultChain } = useMemo(() => { + const defaultChain = wagmiChainMap[defaultChainId]; + return { + supportedChains: [defaultChain] as ChainsList, + defaultChain, + }; + }, [defaultChainId]); + + const getRpcUrlByChainId = useGetRpcUrlByChainId(); + + const backendRPC: Record = useMemo( + () => ({ [defaultChainId]: getRpcUrlByChainId(defaultChainId) }), + [defaultChainId, getRpcUrlByChainId], + ); + const transportMap = useWeb3Transport(supportedChains, backendRPC); + + const mainnetConfig = useMemo(() => { + const batchConfig = { + wait: config.PROVIDER_BATCH_TIME, + batchSize: config.PROVIDER_MAX_BATCH, + }; + + const rpcUrlMainnet = getRpcUrlByChainId(CHAINS.Mainnet); + + return createConfig({ + chains: [wagmiChains.mainnet], + ssr: true, + connectors: [], + batch: { + multicall: false, + }, + pollingInterval: config.PROVIDER_POLLING_INTERVAL, + transports: { + [wagmiChains.mainnet.id]: fallback([ + // api/rpc + http(rpcUrlMainnet, { + batch: batchConfig, + name: rpcUrlMainnet, + }), + // fallback rpc from wagmi.chains like cloudfare-eth + http(undefined, { + batch: batchConfig, + name: 'default public RPC URL', + }), + ]), + }, + }); + }, [getRpcUrlByChainId]); + + const publicClientMainnet = usePublicClient({ + config: mainnetConfig, + }); + + const { wagmiConfig, reefKnotConfig, walletsModalConfig } = useMemo(() => { + return getDefaultConfig({ + // Reef-Knot config args + rpc: backendRPC, + defaultChain: defaultChain, + walletconnectProjectId, + walletsList: WalletsListEthereum, + + // Wagmi config args + transports: transportMap, + chains: supportedChains, + autoConnect: isWalletConnectionAllowed, + ssr: true, + pollingInterval: config.PROVIDER_POLLING_INTERVAL, + batch: { + multicall: false, + }, + + // Wallets config args + ...getDefaultWalletsModalConfig(), + ...walletMetricProps, + walletsPinned: WALLETS_PINNED, + }); + }, [ + backendRPC, + supportedChains, + defaultChain, + walletconnectProjectId, + isWalletConnectionAllowed, + transportMap, + ]); + + return ( + + {/* default wagmi autoConnect, MUST be false in our case, because we use custom autoConnect from Reef Knot */} + + + + + {children} + + + + ); +}; diff --git a/next.config.mjs b/next.config.mjs index 1a5f7f323..6a655c8d6 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,20 +1,45 @@ +import fs from 'fs'; +import path from 'path'; +// eslint-disable-next-line import/no-extraneous-dependencies import NextBundleAnalyzer from '@next/bundle-analyzer'; import buildDynamics from './scripts/build-dynamics.mjs'; import generateBuildId from './scripts/generate-build-id.mjs'; +import { logEnvironmentVariables } from './scripts/log-environment-variables.mjs'; +import { startupCheckRPCs } from './scripts/startup-checks/rpc.mjs'; +import { startupCheckValidationFile } from './scripts/startup-checks/validation-file.mjs'; +logEnvironmentVariables(); buildDynamics(); +if (process.env.RUN_STARTUP_CHECKS === 'true') { + void startupCheckRPCs(); + void startupCheckValidationFile(); +} + // https://nextjs.org/docs/pages/api-reference/next-config-js/basePath const basePath = process.env.BASE_PATH; const developmentMode = process.env.NODE_ENV === 'development'; +const moduleMode = (process.env.MODULE || 'csm').toUpperCase(); const isIPFSMode = !!process.env.IPFS_MODE; const maintenance = !!process.env.MAINTENANCE; // TODO: load from runtime config +// Load devnet contract addresses from JSON file if specified +let devnetAddresses = null; +if (process.env.DEVNET_ADDRESSES_FILE_PATH) { + try { + const filePath = path.resolve(process.env.DEVNET_ADDRESSES_FILE_PATH); + devnetAddresses = JSON.parse(fs.readFileSync(filePath, 'utf-8')); + } catch (e) { + console.warn('Failed to load devnet addresses:', e.message); + } +} + // cache control export const CACHE_CONTROL_HEADER = 'x-cache-control'; export const CACHE_CONTROL_PAGES = [ '/manifest.json', + '/manifest-cm.json', '/favicon:size*', '/', '/runtime/window-env.js', @@ -111,8 +136,30 @@ export default withBundleAnalyzer({ }, ], }, + + // Handle JSON imports with 'with' assertions syntax from node_modules + // by removing the assertions, because next v12 does not support them, which causes build error. + // Specifically targeting affected modules here + { + test: /node_modules\/@base-org\/account.*\.js$/, + use: { + loader: 'string-replace-loader', + options: { + search: 'with\\s*\\{\\s*type:\\s*[\'"]json[\'"]\\s*\\}', + replace: '', + flags: 'g', + }, + }, + }, ); + // Fixes warning about missing dependency @react-native-async-storage/async-storage, + // which comes from @metamask/sdk v0.33.1 + // See https://github.com/MetaMask/metamask-sdk/issues/1376 + config.resolve.fallback = { + '@react-native-async-storage/async-storage': false, + }; + return config; }, async headers() { @@ -143,7 +190,7 @@ export default withBundleAnalyzer({ }, { // required for gnosis save apps - source: '/manifest.json', + source: '/manifest:suffix(-[a-z]+)?.json', headers: [{ key: 'Access-Control-Allow-Origin', value: '*' }], }, ...CACHE_CONTROL_PAGES.map((page) => ({ @@ -161,33 +208,31 @@ export default withBundleAnalyzer({ maintenance, defaultChain: process.env.DEFAULT_CHAIN, + rpcUrls_1: process.env.EL_RPC_URLS_1, - rpcUrls_17000: process.env.EL_RPC_URLS_17000, - ethplorerApiKey: process.env.ETHPLORER_API_KEY, + rpcUrls_560048: process.env.EL_RPC_URLS_560048, + clApiUrls_1: process.env.CL_API_URLS_1, - clApiUrls_17000: process.env.CL_API_URLS_17000, + clApiUrls_560048: process.env.CL_API_URLS_560048, - oneInchApiKey: process.env.ONE_INCH_API_KEY, + migalabsApiUrl: process.env.ETHSEER_API_URL, + migalabsApiToken: process.env.ETHSEER_API_TOKEN, cspTrustedHosts: process.env.CSP_TRUSTED_HOSTS, cspReportUri: process.env.CSP_REPORT_URI, cspReportOnly: process.env.CSP_REPORT_ONLY, - subgraphMainnet: process.env.SUBGRAPH_MAINNET, - subgraphGoerli: process.env.SUBGRAPH_GOERLI, - subgraphHolesky: process.env.SUBGRAPH_HOLESKY, - subgraphRequestTimeout: process.env.SUBGRAPH_REQUEST_TIMEOUT, - rateLimit: process.env.RATE_LIMIT, rateLimitTimeFrame: process.env.RATE_LIMIT_TIME_FRAME, - - ethAPIBasePath: process.env.ETH_API_BASE_PATH, - rewardsBackendAPI: process.env.REWARDS_BACKEND, + validationAPI: process.env.VALIDATION_SERVICE_BASE_PATH, + validationFilePath: process.env.VALIDATION_FILE_PATH, }, // ATTENTION: If you add a new variable you should declare it in `global.d.ts` publicRuntimeConfig: { basePath, developmentMode, + module: moduleMode, + devnetAddresses, }, }); diff --git a/package.json b/package.json index 95877de47..110c243db 100644 --- a/package.json +++ b/package.json @@ -1,113 +1,114 @@ { "name": "lido-csm-widget", - "version": "1.2.2", + "version": "2.0.0", "private": true, "type": "module", "license": "GPL-3.0-or-later", "scripts": { "dev": "next dev", + "dev:cm": "MODULE=cm next dev", "build": "next build", "build:analyze": "ANALYZE_BUNDLE=true next build", "start": "NODE_OPTIONS='-r next-logger' next start", "lint": "eslint --ext ts,tsx,js,mjs .", "lint:fix": "yarn lint --fix", "types": "tsc --noEmit", - "typechain": "typechain --target=ethers-v5 --out-dir ./generated ./abi/*.json", - "postinstall": "husky install && yarn typechain || true", - "test": "yarn test:e2e", + "postinstall": "husky || true", "test:unit": "jest", - "test:e2e": "playwright test" + "test:setup": "npx playwright install chromium && ./tests/scripts/set_up_keys_generator.sh && yarn test:setup:fork", + "test:setup:fork": "./tests/scripts/install_foundry.sh", + "test:cm:e2e": "playwright test --config=./tests/cm-widget/playwright.config.ts", + "test:csm:e2e": "playwright test --config=./tests/csm-widget/playwright.config.ts", + "test:csm:ui": "playwright test --ui --config=./tests/csm-widget/playwright.config.ts", + "test:cm:ui": "playwright test --ui --config=./tests/cm-widget/playwright.config.ts" }, "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/contracts": "^5.7.0", - "@ethersproject/providers": "^5.7.0", - "@ethersproject/units": "^5.7.0", - "@lido-sdk/constants": "^3.2.1", - "@lido-sdk/contracts": "^3.0.4", - "@lido-sdk/fetch": "^2.1.12", - "@lido-sdk/helpers": "^1.5.1", - "@lido-sdk/providers": "^1.4.14", - "@lido-sdk/react": "^2.0.5", + "@base-org/account": "^2.5.1", + "@coinbase/wallet-sdk": "^4.3.6", + "@gemini-wallet/core": "~0.3.1", "@lidofinance/address": "^1.4.0", - "@lidofinance/analytics-matomo": "^0.51.0", - "@lidofinance/api-logger": "^0.47.0", - "@lidofinance/api-metrics": "^0.47.0", - "@lidofinance/api-rpc": "^0.47.0", - "@lidofinance/eth-api-providers": "^0.47.0", - "@lidofinance/eth-providers": "^0.47.0", - "@lidofinance/lido-ui": "^3.26.0", - "@lidofinance/next-api-wrapper": "^0.47.0", - "@lidofinance/next-ip-rate-limit": "^0.47.0", - "@lidofinance/next-pages": "^0.47.0", - "@lidofinance/rpc": "^0.47.0", - "@lidofinance/satanizer": "^0.47.0", + "@lidofinance/analytics-matomo": "^0.59.0", + "@lidofinance/api-logger": "^0.59.0", + "@lidofinance/api-metrics": "^0.59.0", + "@lidofinance/api-rpc": "^0.59.0", + "@lidofinance/eth-api-providers": "^0.59.0", + "@lidofinance/eth-providers": "^0.59.0", + "@lidofinance/lido-csm-sdk": "^2.0.0-alpha.70", + "@lidofinance/lido-ethereum-sdk": "^4.8.0", + "@lidofinance/lido-ui": "^3.42.1", + "@lidofinance/next-api-wrapper": "^0.59.0", + "@lidofinance/next-ip-rate-limit": "^0.59.0", + "@lidofinance/next-pages": "^0.59.0", + "@lidofinance/rpc": "^0.59.0", + "@lidofinance/satanizer": "^0.59.0", + "@lidofinance/secret-guard-reporter": "^1.1.0", + "@metamask/sdk": "~0.33.1", "@openzeppelin/merkle-tree": "^1.0.7", - "bignumber.js": "9.1.2", + "@safe-global/safe-apps-provider": "~0.18.6", + "@safe-global/safe-apps-sdk": "^9.1.0", + "@tanstack/react-query": "^5.85.6", + "@walletconnect/ethereum-provider": "^2.23.8", "copy-to-clipboard": "^3.3.1", "cors": "^2.8.5", "date-fns": "2.29.2", - "ethers": "^5.7.2", "fs-extra": "^11.2.0", - "gray-matter": "^4.0.3", - "js-cookie": "^3.0.1", - "lodash": "^4.17.21", + "html2canvas": "^1.4.1", + "lodash": "^4.18.1", "memory-cache": "^0.2.0", "ms": "^2.1.3", - "next": "^12.3.4", + "next": "^12.3.5", "next-logger": "^3.0.2", "next-secure-headers": "^2.2.0", "nprogress": "^0.2.0", - "prom-client": "^14.0.1", + "porto": "~0.2.35", + "prom-client": "^15", "raw-loader": "^4.0.2", "react": "^18.2.0", - "react-device-detect": "^2.2.2", + "react-canvas-confetti": "^2.0.7", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", - "react-hook-form": "^7.52.1", - "react-is": "^18.3.1", - "react-transition-group": "^4.4.2", - "reef-knot": "^4.2.0", - "remark": "^13.0.0", - "remark-external-links": "^8.0.0", - "remark-html": "^13.0.1", + "react-hook-form": "^7.60.0", + "reef-knot": "8.1.1", "siwe": "^3.0.0", "styled-components": "^5.3.5", - "swr": "^2.2.5", - "tiny-async-pool": "^2.1.0", "tiny-invariant": "^1.1.0", - "uuid": "^8.3.2", - "wagmi": "0.12.19" + "uuid": "^14.0.0", + "viem": "2.46.0", + "wagmi": "3.4.1", + "zod": "^4.1.12" }, "devDependencies": { - "@commitlint/cli": "^17.4.4", - "@commitlint/config-conventional": "^17.4.4", - "@commitlint/prompt": "^17.4.4", - "@lidofinance/eslint-config": "^0.43.0", + "@commitlint/cli": "^21", + "@commitlint/config-conventional": "^21", + "@commitlint/prompt": "^21", + "@lidofinance/browser-service": "1.11.2", + "@lidofinance/chat-reporter": "1.9.0", + "@lidofinance/eslint-config": "^0.59.0", + "@lidofinance/pg-reporter": "1.3.0", + "@lidofinance/wallets-testing-extensions": "1.3.1", + "@lidofinance/wallets-testing-nodes": "1.10.0", + "@lidofinance/wallets-testing-wallets": "1.49.2", + "@nestjs/common": "^10.4.16", "@next/bundle-analyzer": "^13.2.4", "@next/eslint-plugin-next": "^13.4.13", - "@playwright/test": "^1.29.2", + "@playwright/test": "1.61.1", + "@scure/bip39": "2.2.0", "@svgr/webpack": "8.1.0", - "@typechain/ethers-v5": "^11.1.2", - "@types/jest": "28.1.6", - "@types/js-cookie": "^3.0.0", + "@types/jest": "^30", "@types/lodash": "^4.14.186", - "@types/memory-cache": "0.2.2", - "@types/ms": "^0.7.31", - "@types/node": "^18.6.1", + "@types/memory-cache": "^0.2.6", + "@types/ms": "^2", + "@types/node": "^24", "@types/nprogress": "^0.2.0", "@types/react": "^18.2.22", "@types/react-transition-group": "^4.4.3", "@types/styled-components": "^5.1.23", "@types/styled-system": "^5.1.17", - "@types/uuid": "^8.3.2", "@types/winston": "^2.4.4", "@typescript-eslint/eslint-plugin": "^6.2.1", "@typescript-eslint/parser": "^6.2.1", "eslint": "^8.46.0", - "eslint-config-prettier": "^9.0.0", + "eslint-config-prettier": "^10", "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.28.0", @@ -118,21 +119,47 @@ "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-sonarjs": "^0.20.0", "eslint-plugin-unicorn": "^48.0.1", - "husky": "^7.0.1", - "jest": "^29.5.0", + "husky": "^9", + "jest": "^30", "jsonschema": "^1.4.1", - "lint-staged": "^13.2.3", - "playwright": "^1.29.2", + "lint-staged": "^17", + "playwright-qase-reporter": "^2.5.5", "prettier": "^3.3.3", - "ts-jest": "^29.1.0", + "qase-javascript-commons": "^2.7.5", + "qaseio": "^2.4.3", + "string-replace-loader": "^3.3.0", + "ts-jest": "^29", "typechain": "^8.1.1", - "typescript": "^5.4.5", + "typescript": "^5.7.3", "url-loader": "^4.1.1", "webpack-preprocessor-loader": "^1.3.0" }, "resolutions": { - "postcss": "^8.4.31", - "crypto-js": "^4.2.0" + "@types/react": "^18.3.31", + "@types/react-dom": "^18.3.0", + "postcss": "^8.5.10", + "crypto-js": "^4.2.0", + "wrap-ansi": "7.0.0", + "@noble/hashes": "^1.8.0", + "elliptic": "^6.6.1", + "minimatch": "^3.1.4", + "js-yaml": "^4.3.0", + "follow-redirects": "^1.16.0", + "secp256k1": "^4.0.4", + "form-data": "^4.0.6", + "@babel/core": "^7.26.10", + "@babel/helpers": "^7.26.10", + "@babel/runtime": "^7.26.10", + "@babel/plugin-transform-modules-systemjs": "^7.29.4", + "yaml": "^2.8.3", + "h3": "^1.15.9", + "hono": "^4.12.27", + "axios": "^1.16.0", + "micromatch": "^4.0.8", + "uuid": "^14.0.0", + "bn.js": "^5.2.3", + "fast-uri": "^3.1.2", + "ws": "^8.20.1" }, "lint-staged": { "./**/*.{ts,tsx}": [ @@ -145,5 +172,11 @@ "browserslist": [ "> 1%, last 2 versions, not dead", "last 1 ios_saf major versions" - ] + ], + "engines": { + "node": ">=24.0.0 <25.0.0" + }, + "volta": { + "node": "24.14.0" + } } diff --git a/pages/404.tsx b/pages/404.tsx index f39ae91d8..fbcc575d3 100644 --- a/pages/404.tsx +++ b/pages/404.tsx @@ -1,5 +1,4 @@ import { ServicePage } from '@lidofinance/lido-ui'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; import { GetStaticProps } from 'next'; import Head from 'next/head'; import { FC } from 'react'; @@ -12,7 +11,7 @@ const StyledServicePage = styled(ServicePage)` `; const Page404: FC = () => ( - + Lido | Page Not Found diff --git a/pages/500.tsx b/pages/500.tsx index 2fb8c1d90..03bb22795 100644 --- a/pages/500.tsx +++ b/pages/500.tsx @@ -1,12 +1,11 @@ import { ServicePage } from '@lidofinance/lido-ui'; -import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events'; import { GetStaticProps } from 'next'; import Head from 'next/head'; import { FC } from 'react'; import { Layout } from 'shared/layout'; const Page500: FC = () => ( - + Lido | Internal Server Error diff --git a/pages/_app.tsx b/pages/_app.tsx index 1b12e12b8..05e04036e 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,17 +1,17 @@ -import { AppProps } from 'next/app'; -import Head from 'next/head'; -import 'nprogress/nprogress.css'; -import { memo } from 'react'; - -import { CookiesTooltip, ToastContainer } from '@lidofinance/lido-ui'; +import 'utils/zod-jitless'; +import { ToastContainer } from '@lidofinance/lido-ui'; import { config, SecretConfigType } from 'config'; import { withCsp } from 'config/csp'; -import { FaqItem } from 'lib/getFaq'; +import { moduleMeta } from 'consts/module'; +import { AppProps } from 'next/app'; +import Head from 'next/head'; +import 'nprogress/nprogress.css'; import { Providers } from 'providers'; -import { FaqContext } from 'providers/faq-provider'; -import { BackgroundGradient } from 'shared/components'; -import { nprogress } from 'utils'; +import { memo } from 'react'; +import { BackgroundGradient, SecurityStatusBanner } from 'shared/components'; +import { SVGGradientDefs } from 'shared/components/svg-gradient-defs/svg-gradient-defs'; +import { AddressValidationFile, nprogress } from 'utils'; // Visualize route changes nprogress(); @@ -25,39 +25,39 @@ const App = (props: AppProps) => { const MemoApp = memo(App); type AppParams = Partial> & { + validationFile?: AddressValidationFile; isError?: boolean; - faqList?: FaqItem[]; }; const AppWrapper = (props: AppProps): JSX.Element => { const { ...rest } = props; return ( - - - {/* see https://nextjs.org/docs/messages/no-document-viewport-meta */} - - - CSM | Lido - - + {/* see https://nextjs.org/docs/messages/no-document-viewport-meta */} + + - - - - - + {moduleMeta.shortTitle} | Lido + + + + + + + ); }; diff --git a/pages/_document.tsx b/pages/_document.tsx index c104b21a5..64e064bb3 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -12,8 +12,10 @@ import { Fonts, LidoUIHead } from '@lidofinance/lido-ui'; import { config } from 'config'; import { contentSecurityPolicy } from 'config/csp'; +import { moduleMeta } from 'consts/module'; +import { FiraCodeFont } from 'styles'; -let host = 'https://csm.lido.fi'; +let host: string = moduleMeta.host; const secureHeaders = createHeadersObject({ contentSecurityPolicy }); const cspMetaTagContent = @@ -55,15 +57,15 @@ export default class MyDocument extends Document { } get metaTitle(): string { - return 'Community Staking Module | Lido'; + return `${moduleMeta.title} | Lido`; } get metaDescription(): string { - return 'The Community Staking Module is a permissionless staking module aimed at attracting community stakers to participate in the Lido on Ethereum protocol as Node Operators.'; + return moduleMeta.description; } get metaPreviewImgUrl(): string { - return `${host}/preview.png`; + return `${host}/${moduleMeta.previewFile}`; } render(): JSX.Element { @@ -127,6 +129,7 @@ export default class MyDocument extends Document { + {/* eslint-disable-next-line @next/next/no-sync-scripts */}