Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
dc05559
feat(forks): recognise gloas and derive slot phases per fork
samcm Jul 16, 2026
d429b8e
chore(api): regenerate client with gloas ePBS tables
samcm Jul 16, 2026
c6528ea
feat(slots): ePBS payload lifecycle card on slot detail
samcm Jul 16, 2026
6c76be5
feat(slots): move ePBS payload lifecycle into its own tab with the bi…
samcm Jul 16, 2026
3c74d00
feat(live): ePBS payload and bid race in the slot HUD
samcm Jul 16, 2026
8143186
fix(live): clamp playhead to bounds intersection and poll near-head s…
samcm Jul 16, 2026
dafb341
feat(live): PTC arrival stream and payload propagation wave
samcm Jul 16, 2026
5495804
feat(live): merge PTC stream into the arrivals chart and sidebar time…
samcm Jul 16, 2026
2568b3e
fix(live): cap how far one lagging table holds playback behind head
samcm Jul 16, 2026
c5d7546
feat(live): per-node block and payload rows in the sidebar timeline
samcm Jul 16, 2026
39bde61
fix(live): location-first labels on per-node sidebar rows
samcm Jul 16, 2026
a066575
fix(live): keep per-node sidebar rows inside the row width
samcm Jul 16, 2026
0f1ee2b
fix(live): render sidebar rows exactly as master does
samcm Jul 16, 2026
09ed9f6
fix(forks): drop the FOCIL claim from gloas metadata
samcm Jul 16, 2026
9d9309f
feat(slots): real gloas execution data and payload verdicts in the list
samcm Jul 17, 2026
23612b1
fix(live): show only real execution facts in the gloas HUD lane
samcm Jul 17, 2026
66ef1cc
fix(slots): accept PTC votes as block evidence in payload status
samcm Jul 17, 2026
ed1fba6
feat(slots): cap the bid race chart at the top ten builders
samcm Jul 17, 2026
ebcb6b3
feat(slots): drive the bid race from the auction frontier
samcm Jul 17, 2026
2cb8249
feat(slots): payload propagation and PTC arrivals on the Payload tab
samcm Jul 17, 2026
c46c83a
fix(slots): apply title prop on all arrivals chart render paths
samcm Jul 17, 2026
692ada0
feat(overview): payload delivery rate chart
samcm Jul 17, 2026
c40a81f
feat(slots): payload reveal and PTC vote lanes in the timeline waterfall
samcm Jul 17, 2026
2df02a6
test(live): include intersection aggregates in bounds mock
samcm Jul 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14,641 changes: 10,363 additions & 4,278 deletions src/api/@tanstack/react-query.gen.ts

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions src/api/client.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import type { ClientOptions as ClientOptions2 } from './types.gen';
* `setConfig()`. This is useful for example if you're using Next.js
* to ensure your client always has the correct values.
*/
export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;
export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (
override?: Config<ClientOptions & T>
) => Config<Required<ClientOptions> & T>;

export const client = createClient(createClientConfig(createConfig<ClientOptions2>({ baseUrl: 'https://cbt-api-mainnet.analytics.production.platform.ethpandaops.io' })));
export const client = createClient(
createClientConfig(createConfig<ClientOptions2>({ baseUrl: 'http://localhost:9091' }))
);
9 changes: 3 additions & 6 deletions src/api/client/client.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const createClient = (config: Config = {}): Client => {
return { opts, url };
};

const request: Client['request'] = async (options) => {
const request: Client['request'] = async options => {
// @ts-expect-error
const { opts, url } = await beforeRequest(options);
const requestInit: ReqInit = {
Expand Down Expand Up @@ -128,9 +128,7 @@ export const createClient = (config: Config = {}): Client => {

if (response.ok) {
const parseAs =
(opts.parseAs === 'auto'
? getParseAs(response.headers.get('Content-Type'))
: opts.parseAs) ?? 'json';
(opts.parseAs === 'auto' ? getParseAs(response.headers.get('Content-Type')) : opts.parseAs) ?? 'json';

if (response.status === 204 || response.headers.get('Content-Length') === '0') {
let emptyData: any;
Expand Down Expand Up @@ -234,8 +232,7 @@ export const createClient = (config: Config = {}): Client => {
};
};

const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
request({ ...options, method });
const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) => request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
Expand Down
6 changes: 1 addition & 5 deletions src/api/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@

export type { Auth } from '../core/auth.gen';
export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
export {
formDataBodySerializer,
jsonBodySerializer,
urlSearchParamsBodySerializer,
} from '../core/bodySerializer.gen';
export { formDataBodySerializer, jsonBodySerializer, urlSearchParamsBodySerializer } from '../core/bodySerializer.gen';
export { buildClientParams } from '../core/params.gen';
export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
export { createClient } from './client.gen';
Expand Down
26 changes: 8 additions & 18 deletions src/api/client/types.gen.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
// This file is auto-generated by @hey-api/openapi-ts

import type { Auth } from '../core/auth.gen';
import type {
ServerSentEventsOptions,
ServerSentEventsResult,
} from '../core/serverSentEvents.gen';
import type { ServerSentEventsOptions, ServerSentEventsResult } from '../core/serverSentEvents.gen';
import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen';
import type { Middleware } from './utils.gen';

Expand Down Expand Up @@ -66,11 +63,7 @@ export interface RequestOptions<
}>,
Pick<
ServerSentEventsOptions<TData>,
| 'onSseError'
| 'onSseEvent'
| 'sseDefaultRetryDelay'
| 'sseMaxRetryAttempts'
| 'sseMaxRetryDelay'
'onSseError' | 'onSseEvent' | 'sseDefaultRetryDelay' | 'sseMaxRetryAttempts' | 'sseMaxRetryDelay'
> {
/**
* Any body that you want to add to your request.
Expand Down Expand Up @@ -142,7 +135,7 @@ type MethodFn = <
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = 'fields',
>(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;

type SseFn = <
Expand All @@ -151,7 +144,7 @@ type SseFn = <
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = 'fields',
>(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>
) => Promise<ServerSentEventsResult<TData, TError>>;

type RequestFn = <
Expand All @@ -161,7 +154,7 @@ type RequestFn = <
TResponseStyle extends ResponseStyle = 'fields',
>(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> &
Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 'method'>,
Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 'method'>
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;

type BuildUrlFn = <
Expand All @@ -172,7 +165,7 @@ type BuildUrlFn = <
url: string;
},
>(
options: TData & Options<TData>,
options: TData & Options<TData>
) => string;

export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
Expand All @@ -188,7 +181,7 @@ export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn>
* to ensure your client always has the correct values.
*/
export type CreateClientConfig<T extends ClientOptions = ClientOptions> = (
override?: Config<ClientOptions & T>,
override?: Config<ClientOptions & T>
) => Config<Required<ClientOptions> & T>;

export interface TDataShape {
Expand All @@ -206,8 +199,5 @@ export type Options<
ThrowOnError extends boolean = boolean,
TResponse = unknown,
TResponseStyle extends ResponseStyle = 'fields',
> = OmitKeys<
RequestOptions<TResponse, TResponseStyle, ThrowOnError>,
'body' | 'path' | 'query' | 'url'
> &
> = OmitKeys<RequestOptions<TResponse, TResponseStyle, ThrowOnError>, 'body' | 'path' | 'query' | 'url'> &
([TData] extends [never] ? unknown : Omit<TData, 'url'>);
51 changes: 12 additions & 39 deletions src/api/client/utils.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,11 @@
import { getAuthToken } from '../core/auth.gen';
import type { QuerySerializerOptions } from '../core/bodySerializer.gen';
import { jsonBodySerializer } from '../core/bodySerializer.gen';
import {
serializeArrayParam,
serializeObjectParam,
serializePrimitiveParam,
} from '../core/pathSerializer.gen';
import { serializeArrayParam, serializeObjectParam, serializePrimitiveParam } from '../core/pathSerializer.gen';
import { getUrl } from '../core/utils.gen';
import type { Client, ClientOptions, Config, RequestOptions } from './types.gen';

export const createQuerySerializer = <T = unknown>({
parameters = {},
...args
}: QuerySerializerOptions = {}) => {
export const createQuerySerializer = <T = unknown>({ parameters = {}, ...args }: QuerySerializerOptions = {}) => {
const querySerializer = (queryParams: T) => {
const search: string[] = [];
if (queryParams && typeof queryParams === 'object') {
Expand Down Expand Up @@ -86,9 +79,7 @@ export const getParseAs = (contentType: string | null): Exclude<Config['parseAs'
return 'formData';
}

if (
['application/', 'audio/', 'image/', 'video/'].some((type) => cleanContent.startsWith(type))
) {
if (['application/', 'audio/', 'image/', 'video/'].some(type => cleanContent.startsWith(type))) {
return 'blob';
}

Expand All @@ -103,16 +94,12 @@ const checkForExistence = (
options: Pick<RequestOptions, 'auth' | 'query'> & {
headers: Headers;
},
name?: string,
name?: string
): boolean => {
if (!name) {
return false;
}
if (
options.headers.has(name) ||
options.query?.[name] ||
options.headers.get('Cookie')?.includes(`${name}=`)
) {
if (options.headers.has(name) || options.query?.[name] || options.headers.get('Cookie')?.includes(`${name}=`)) {
return true;
}
return false;
Expand Down Expand Up @@ -156,7 +143,7 @@ export const setAuthParams = async ({
}
};

export const buildUrl: Client['buildUrl'] = (options) =>
export const buildUrl: Client['buildUrl'] = options =>
getUrl({
baseUrl: options.baseUrl as string,
path: options.path,
Expand Down Expand Up @@ -185,9 +172,7 @@ const headersEntries = (headers: Headers): Array<[string, string]> => {
return entries;
};

export const mergeHeaders = (
...headers: Array<Required<Config>['headers'] | undefined>
): Headers => {
export const mergeHeaders = (...headers: Array<Required<Config>['headers'] | undefined>): Headers => {
const mergedHeaders = new Headers();
for (const header of headers) {
if (!header) {
Expand All @@ -206,10 +191,7 @@ export const mergeHeaders = (
} else if (value !== undefined) {
// assume object headers are meant to be JSON stringified, i.e. their
// content value in OpenAPI specification is 'application/json'
mergedHeaders.set(
key,
typeof value === 'object' ? JSON.stringify(value) : (value as string),
);
mergedHeaders.set(key, typeof value === 'object' ? JSON.stringify(value) : (value as string));
}
}
}
Expand All @@ -220,16 +202,12 @@ type ErrInterceptor<Err, Res, Req, Options> = (
error: Err,
response: Res,
request: Req,
options: Options,
options: Options
) => Err | Promise<Err>;

type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;

type ResInterceptor<Res, Req, Options> = (
response: Res,
request: Req,
options: Options,
) => Res | Promise<Res>;
type ResInterceptor<Res, Req, Options> = (response: Res, request: Req, options: Options) => Res | Promise<Res>;

class Interceptors<Interceptor> {
fns: Array<Interceptor | null> = [];
Expand Down Expand Up @@ -278,12 +256,7 @@ export interface Middleware<Req, Res, Err, Options> {
response: Interceptors<ResInterceptor<Res, Req, Options>>;
}

export const createInterceptors = <Req, Res, Err, Options>(): Middleware<
Req,
Res,
Err,
Options
> => ({
export const createInterceptors = <Req, Res, Err, Options>(): Middleware<Req, Res, Err, Options> => ({
error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),
request: new Interceptors<ReqInterceptor<Req, Options>>(),
response: new Interceptors<ResInterceptor<Res, Req, Options>>(),
Expand All @@ -306,7 +279,7 @@ const defaultHeaders = {
};

export const createConfig = <T extends ClientOptions = ClientOptions>(
override: Config<Omit<ClientOptions, keyof T> & T> = {},
override: Config<Omit<ClientOptions, keyof T> & T> = {}
): Config<Omit<ClientOptions, keyof T> & T> => ({
...jsonBodySerializer,
headers: defaultHeaders,
Expand Down
2 changes: 1 addition & 1 deletion src/api/core/auth.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface Auth {

export const getAuthToken = async (
auth: Auth,
callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,
callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken
): Promise<string | undefined> => {
const token = typeof callback === 'function' ? await callback(auth) : callback;

Expand Down
8 changes: 3 additions & 5 deletions src/api/core/bodySerializer.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,15 @@ const serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value:
};

export const formDataBodySerializer = {
bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(
body: T,
): FormData => {
bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(body: T): FormData => {
const data = new FormData();

Object.entries(body).forEach(([key, value]) => {
if (value === undefined || value === null) {
return;
}
if (Array.isArray(value)) {
value.forEach((v) => serializeFormDataPair(data, key, v));
value.forEach(v => serializeFormDataPair(data, key, v));
} else {
serializeFormDataPair(data, key, value);
}
Expand All @@ -73,7 +71,7 @@ export const urlSearchParamsBodySerializer = {
return;
}
if (Array.isArray(value)) {
value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));
value.forEach(v => serializeUrlSearchParamsPair(data, key, v));
} else {
serializeUrlSearchParamsPair(data, key, value);
}
Expand Down
18 changes: 7 additions & 11 deletions src/api/core/pathSerializer.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ export const serializeArrayParam = ({
value: unknown[];
}) => {
if (!explode) {
const joinedValues = (
allowReserved ? value : value.map((v) => encodeURIComponent(v as string))
).join(separatorArrayNoExplode(style));
const joinedValues = (allowReserved ? value : value.map(v => encodeURIComponent(v as string))).join(
separatorArrayNoExplode(style)
);
switch (style) {
case 'label':
return `.${joinedValues}`;
Expand All @@ -91,7 +91,7 @@ export const serializeArrayParam = ({

const separator = separatorArrayExplode(style);
const joinedValues = value
.map((v) => {
.map(v => {
if (style === 'label' || style === 'simple') {
return allowReserved ? v : encodeURIComponent(v as string);
}
Expand All @@ -106,18 +106,14 @@ export const serializeArrayParam = ({
return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
};

export const serializePrimitiveParam = ({
allowReserved,
name,
value,
}: SerializePrimitiveParam) => {
export const serializePrimitiveParam = ({ allowReserved, name, value }: SerializePrimitiveParam) => {
if (value === undefined || value === null) {
return '';
}

if (typeof value === 'object') {
throw new Error(
'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.',
'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.'
);
}

Expand Down Expand Up @@ -164,7 +160,7 @@ export const serializeObjectParam = ({
allowReserved,
name: style === 'deepObject' ? `${name}[${key}]` : key,
value: v as string,
}),
})
)
.join(separator);
return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
Expand Down
8 changes: 1 addition & 7 deletions src/api/core/queryKeySerializer.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@
/**
* JSON-friendly union that mirrors what Pinia Colada can hash.
*/
export type JsonValue =
| null
| string
| number
| boolean
| JsonValue[]
| { [key: string]: JsonValue };
export type JsonValue = null | string | number | boolean | JsonValue[] | { [key: string]: JsonValue };

/**
* Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes.
Expand Down
8 changes: 2 additions & 6 deletions src/api/core/serverSentEvents.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,7 @@ export interface StreamEvent<TData = unknown> {
}

export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {
stream: AsyncGenerator<
TData extends Record<string, unknown> ? TData[keyof TData] : TData,
TReturn,
TNext
>;
stream: AsyncGenerator<TData extends Record<string, unknown> ? TData[keyof TData] : TData, TReturn, TNext>;
};

export const createSseClient = <TData = unknown>({
Expand All @@ -94,7 +90,7 @@ export const createSseClient = <TData = unknown>({
}: ServerSentEventsOptions): ServerSentEventsResult<TData> => {
let lastEventId: string | undefined;

const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
const sleep = sseSleepFn ?? ((ms: number) => new Promise(resolve => setTimeout(resolve, ms)));

const createStream = async function* () {
let retryDelay: number = sseDefaultRetryDelay ?? 3000;
Expand Down
Loading
Loading