fix(explorer): place sensible limits on oracles page queries (#2699)
This commit is contained in:
parent
33e528c569
commit
3188f23439
@ -70,7 +70,7 @@
|
|||||||
"executor": "@nrwl/workspace:run-commands",
|
"executor": "@nrwl/workspace:run-commands",
|
||||||
"options": {
|
"options": {
|
||||||
"commands": [
|
"commands": [
|
||||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.66.1/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.67.3/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Routes } from '../../../routes/route-names';
|
import { Routes } from '../../../routes/route-names';
|
||||||
import { useExplorerMarketQuery } from './__generated__/Market';
|
import { useExplorerMarketQuery } from './__generated__/Market';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
@ -8,6 +7,7 @@ import { t } from '@vegaprotocol/react-helpers';
|
|||||||
|
|
||||||
export type MarketLinkProps = Partial<ComponentProps<typeof Link>> & {
|
export type MarketLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||||
id: string;
|
id: string;
|
||||||
|
showMarketName?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,7 +15,11 @@ export type MarketLinkProps = Partial<ComponentProps<typeof Link>> & {
|
|||||||
* with a link to the markets list. If the name does not come back
|
* with a link to the markets list. If the name does not come back
|
||||||
* it will use the ID instead
|
* it will use the ID instead
|
||||||
*/
|
*/
|
||||||
const MarketLink = ({ id, ...props }: MarketLinkProps) => {
|
const MarketLink = ({
|
||||||
|
id,
|
||||||
|
showMarketName = true,
|
||||||
|
...props
|
||||||
|
}: MarketLinkProps) => {
|
||||||
const { data, error, loading } = useExplorerMarketQuery({
|
const { data, error, loading } = useExplorerMarketQuery({
|
||||||
variables: { id },
|
variables: { id },
|
||||||
});
|
});
|
||||||
@ -37,11 +41,24 @@ const MarketLink = ({ id, ...props }: MarketLinkProps) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
if (showMarketName) {
|
||||||
<Link className="underline" {...props} to={`/${Routes.MARKETS}#${id}`}>
|
return (
|
||||||
{label}
|
<Link
|
||||||
</Link>
|
className="underline"
|
||||||
);
|
{...props}
|
||||||
|
to={`/${Routes.MARKETS}#${id}`}
|
||||||
|
title={id}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Link className="underline" {...props} to={`/${Routes.MARKETS}#${id}`}>
|
||||||
|
{id}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MarketLink;
|
export default MarketLink;
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
import { Routes } from '../../../routes/route-names';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import type { ComponentProps } from 'react';
|
||||||
|
|
||||||
|
export type OracleLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const OracleLink = ({ id, ...props }: OracleLinkProps) => {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
className="underline font-mono"
|
||||||
|
{...props}
|
||||||
|
to={`/${Routes.ORACLES}/${id}`}
|
||||||
|
>
|
||||||
|
{id}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OracleLink;
|
@ -50,6 +50,12 @@ export const TxDetailsOrder = ({
|
|||||||
<code>{deterministicId}</code>
|
<code>{deterministicId}</code>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableCell>{t('Market ID')}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<MarketLink id={marketId} showMarketName={false} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Market')}</TableCell>
|
<TableCell>{t('Market')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
|
@ -51,6 +51,9 @@ fragment ExplorerOracleDataSource on OracleSpec {
|
|||||||
|
|
||||||
fragment ExplorerOracleDataConnection on OracleSpec {
|
fragment ExplorerOracleDataConnection on OracleSpec {
|
||||||
dataConnection {
|
dataConnection {
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
}
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
externalData {
|
externalData {
|
||||||
@ -79,12 +82,21 @@ fragment ExplorerOracleDataConnection on OracleSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
query ExplorerOracleSpecs {
|
query ExplorerOracleSpecs {
|
||||||
oracleSpecsConnection {
|
oracleSpecsConnection(pagination: { first: 50 }) {
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
}
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
...ExplorerOracleDataSource
|
...ExplorerOracleDataSource
|
||||||
...ExplorerOracleDataConnection
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query ExplorerOracleSpecById($id: ID!) {
|
||||||
|
oracleSpec(oracleSpecId: $id) {
|
||||||
|
...ExplorerOracleDataSource
|
||||||
|
...ExplorerOracleDataConnection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,12 +5,19 @@ import * as Apollo from '@apollo/client';
|
|||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
export type ExplorerOracleDataSourceFragment = { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } } };
|
export type ExplorerOracleDataSourceFragment = { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } } };
|
||||||
|
|
||||||
export type ExplorerOracleDataConnectionFragment = { __typename?: 'OracleSpec', dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
export type ExplorerOracleDataConnectionFragment = { __typename?: 'OracleSpec', dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
||||||
|
|
||||||
export type ExplorerOracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
export type ExplorerOracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
|
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
|
||||||
|
|
||||||
|
export type ExplorerOracleSpecByIdQueryVariables = Types.Exact<{
|
||||||
|
id: Types.Scalars['ID'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type ExplorerOracleSpecByIdQuery = { __typename?: 'Query', oracleSpec?: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } | null };
|
||||||
|
|
||||||
export const ExplorerOracleDataSourceFragmentDoc = gql`
|
export const ExplorerOracleDataSourceFragmentDoc = gql`
|
||||||
fragment ExplorerOracleDataSource on OracleSpec {
|
fragment ExplorerOracleDataSource on OracleSpec {
|
||||||
@ -66,7 +73,10 @@ export const ExplorerOracleDataSourceFragmentDoc = gql`
|
|||||||
`;
|
`;
|
||||||
export const ExplorerOracleDataConnectionFragmentDoc = gql`
|
export const ExplorerOracleDataConnectionFragmentDoc = gql`
|
||||||
fragment ExplorerOracleDataConnection on OracleSpec {
|
fragment ExplorerOracleDataConnection on OracleSpec {
|
||||||
dataConnection {
|
dataConnection(pagination: {first: 1}) {
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
}
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
externalData {
|
externalData {
|
||||||
@ -96,7 +106,10 @@ export const ExplorerOracleDataConnectionFragmentDoc = gql`
|
|||||||
`;
|
`;
|
||||||
export const ExplorerOracleSpecsDocument = gql`
|
export const ExplorerOracleSpecsDocument = gql`
|
||||||
query ExplorerOracleSpecs {
|
query ExplorerOracleSpecs {
|
||||||
oracleSpecsConnection {
|
oracleSpecsConnection(pagination: {first: 50}) {
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
}
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
...ExplorerOracleDataSource
|
...ExplorerOracleDataSource
|
||||||
@ -133,4 +146,41 @@ export function useExplorerOracleSpecsLazyQuery(baseOptions?: Apollo.LazyQueryHo
|
|||||||
}
|
}
|
||||||
export type ExplorerOracleSpecsQueryHookResult = ReturnType<typeof useExplorerOracleSpecsQuery>;
|
export type ExplorerOracleSpecsQueryHookResult = ReturnType<typeof useExplorerOracleSpecsQuery>;
|
||||||
export type ExplorerOracleSpecsLazyQueryHookResult = ReturnType<typeof useExplorerOracleSpecsLazyQuery>;
|
export type ExplorerOracleSpecsLazyQueryHookResult = ReturnType<typeof useExplorerOracleSpecsLazyQuery>;
|
||||||
export type ExplorerOracleSpecsQueryResult = Apollo.QueryResult<ExplorerOracleSpecsQuery, ExplorerOracleSpecsQueryVariables>;
|
export type ExplorerOracleSpecsQueryResult = Apollo.QueryResult<ExplorerOracleSpecsQuery, ExplorerOracleSpecsQueryVariables>;
|
||||||
|
export const ExplorerOracleSpecByIdDocument = gql`
|
||||||
|
query ExplorerOracleSpecById($id: ID!) {
|
||||||
|
oracleSpec(oracleSpecId: $id) {
|
||||||
|
...ExplorerOracleDataSource
|
||||||
|
...ExplorerOracleDataConnection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${ExplorerOracleDataSourceFragmentDoc}
|
||||||
|
${ExplorerOracleDataConnectionFragmentDoc}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useExplorerOracleSpecByIdQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useExplorerOracleSpecByIdQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useExplorerOracleSpecByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useExplorerOracleSpecByIdQuery({
|
||||||
|
* variables: {
|
||||||
|
* id: // value for 'id'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useExplorerOracleSpecByIdQuery(baseOptions: Apollo.QueryHookOptions<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useQuery<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>(ExplorerOracleSpecByIdDocument, options);
|
||||||
|
}
|
||||||
|
export function useExplorerOracleSpecByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useLazyQuery<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>(ExplorerOracleSpecByIdDocument, options);
|
||||||
|
}
|
||||||
|
export type ExplorerOracleSpecByIdQueryHookResult = ReturnType<typeof useExplorerOracleSpecByIdQuery>;
|
||||||
|
export type ExplorerOracleSpecByIdLazyQueryHookResult = ReturnType<typeof useExplorerOracleSpecByIdLazyQuery>;
|
||||||
|
export type ExplorerOracleSpecByIdQueryResult = Apollo.QueryResult<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>;
|
@ -37,7 +37,7 @@ describe('Oracle Data view', () => {
|
|||||||
dataConnection: {
|
dataConnection: {
|
||||||
edges: [],
|
edges: [],
|
||||||
},
|
},
|
||||||
} as ExplorerOracleDataConnectionFragment)
|
} as unknown as ExplorerOracleDataConnectionFragment)
|
||||||
);
|
);
|
||||||
expect(res.container).toBeEmptyDOMElement();
|
expect(res.container).toBeEmptyDOMElement();
|
||||||
});
|
});
|
||||||
|
@ -67,7 +67,7 @@ describe('Oracle Signers component', () => {
|
|||||||
__typename: 'Signer',
|
__typename: 'Signer',
|
||||||
signer: {
|
signer: {
|
||||||
__typename: 'PubKey',
|
__typename: 'PubKey',
|
||||||
key: '123',
|
key: '1234567891234567789123456789123456778912345678912345677891234567',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
EthExplorerLinkTypes,
|
EthExplorerLinkTypes,
|
||||||
} from '../../../components/links/eth-explorer-link/eth-explorer-link';
|
} from '../../../components/links/eth-explorer-link/eth-explorer-link';
|
||||||
import { TableRow, TableCell, TableHeader } from '../../../components/table';
|
import { TableRow, TableCell, TableHeader } from '../../../components/table';
|
||||||
|
import { remove0x } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
import type { SourceType } from './oracle';
|
import type { SourceType } from './oracle';
|
||||||
|
|
||||||
@ -14,7 +15,15 @@ export type Signer = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function getAddressTypeLabel(signer: Signer) {
|
export function getAddressTypeLabel(signer: Signer) {
|
||||||
return signer.__typename === 'ETHAddress' ? 'ETH' : 'Vega';
|
const res = signer.__typename === 'ETHAddress' ? 'ETH' : 'Vega';
|
||||||
|
|
||||||
|
// This is a hack: some older oracles were submitted before proper checks stopped
|
||||||
|
// ETH addresses being returned as Vega addresses
|
||||||
|
if (res === 'Vega' && signer?.key?.length !== 64) {
|
||||||
|
return 'ETH';
|
||||||
|
} else {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAddress(signer: Signer) {
|
export function getAddress(signer: Signer) {
|
||||||
@ -29,6 +38,16 @@ export function getAddressLink(signer: Signer) {
|
|||||||
|
|
||||||
if (signer.__typename === 'ETHAddress') {
|
if (signer.__typename === 'ETHAddress') {
|
||||||
return <EthExplorerLink id={address} type={EthExplorerLinkTypes.address} />;
|
return <EthExplorerLink id={address} type={EthExplorerLinkTypes.address} />;
|
||||||
|
} else if (signer.__typename === 'PubKey' && address.length !== 64) {
|
||||||
|
// This is a hack: some older oracles were submitted before proper checks stopped
|
||||||
|
// ETH addresses being returned as Vega addresses
|
||||||
|
// Hacky 0x prefixing as a bonus
|
||||||
|
return (
|
||||||
|
<EthExplorerLink
|
||||||
|
id={`0x${remove0x(address)}`}
|
||||||
|
type={EthExplorerLinkTypes.address}
|
||||||
|
/>
|
||||||
|
);
|
||||||
} else if (signer.__typename === 'PubKey') {
|
} else if (signer.__typename === 'PubKey') {
|
||||||
return <PartyLink id={address} />;
|
return <PartyLink id={address} />;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import { OracleData } from './oracle-data';
|
|||||||
import { OracleFilter } from './oracle-filter';
|
import { OracleFilter } from './oracle-filter';
|
||||||
import { OracleDetailsType } from './oracle-details-type';
|
import { OracleDetailsType } from './oracle-details-type';
|
||||||
import { OracleMarkets } from './oracle-markets';
|
import { OracleMarkets } from './oracle-markets';
|
||||||
|
import { OracleSigners } from './oracle-signers';
|
||||||
|
import OracleLink from '../../../components/links/oracle-link/oracle-link';
|
||||||
|
|
||||||
export type SourceType =
|
export type SourceType =
|
||||||
ExplorerOracleDataSourceFragment['dataSourceSpec']['spec']['data']['sourceType'];
|
ExplorerOracleDataSourceFragment['dataSourceSpec']['spec']['data']['sourceType'];
|
||||||
@ -21,36 +23,47 @@ interface OracleDetailsProps {
|
|||||||
id: string;
|
id: string;
|
||||||
dataSource: ExplorerOracleDataSourceFragment;
|
dataSource: ExplorerOracleDataSourceFragment;
|
||||||
dataConnection: ExplorerOracleDataConnectionFragment;
|
dataConnection: ExplorerOracleDataConnectionFragment;
|
||||||
|
// Defaults to false. Hides the count of 'broadcasts' this oracle has seen
|
||||||
|
showBroadcasts?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notes:
|
||||||
|
* - Matched data is really 'Data that matched this oracle' and given oracles are unique
|
||||||
|
* to each market, and each serves either as trading termination or settlement, really
|
||||||
|
* they will only ever see 1 match (most likely). So it should be more like 'Has seen
|
||||||
|
* data' vs 'Has not yet seen data'
|
||||||
|
*/
|
||||||
export const OracleDetails = ({
|
export const OracleDetails = ({
|
||||||
id,
|
id,
|
||||||
dataSource,
|
dataSource,
|
||||||
dataConnection,
|
dataConnection,
|
||||||
|
showBroadcasts = false,
|
||||||
}: OracleDetailsProps) => {
|
}: OracleDetailsProps) => {
|
||||||
const sourceType = dataSource.dataSourceSpec.spec.data.sourceType;
|
const sourceType = dataSource.dataSourceSpec.spec.data.sourceType;
|
||||||
const reportsCount: number = dataConnection.dataConnection.edges?.length || 0;
|
const reportsCount: number = dataConnection.dataConnection.edges?.length || 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<TableWithTbody>
|
<TableWithTbody className="mb-2">
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableHeader scope="row">{t('ID')}</TableHeader>
|
<TableHeader scope="row">{t('ID')}</TableHeader>
|
||||||
<TableCell modifier="bordered">{id}</TableCell>
|
<TableCell modifier="bordered">
|
||||||
|
<OracleLink id={id} />
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<OracleDetailsType type={sourceType.__typename} />
|
<OracleDetailsType type={sourceType.__typename} />
|
||||||
{
|
<OracleSigners sourceType={sourceType} />
|
||||||
// Disabled until https://github.com/vegaprotocol/vega/issues/7286 is released
|
|
||||||
/*<OracleSigners sourceType={sourceType} />*/
|
|
||||||
}
|
|
||||||
<OracleMarkets id={id} />
|
<OracleMarkets id={id} />
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableHeader scope="row">{t('Broadcasts')}</TableHeader>
|
<TableHeader scope="row">{t('Matched data')}</TableHeader>
|
||||||
<TableCell modifier="bordered">{reportsCount}</TableCell>
|
<TableCell modifier="bordered">
|
||||||
|
{showBroadcasts ? reportsCount : reportsCount > 0 ? '✅' : '❌'}
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableWithTbody>
|
</TableWithTbody>
|
||||||
<OracleFilter data={dataSource} />
|
<OracleFilter data={dataSource} />
|
||||||
<OracleData data={dataConnection} />
|
{showBroadcasts ? <OracleData data={dataConnection} /> : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
45
apps/explorer/src/app/routes/oracles/home/index.tsx
Normal file
45
apps/explorer/src/app/routes/oracles/home/index.tsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { RouteTitle } from '../../../components/route-title';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import { useExplorerOracleSpecsQuery } from '../__generated__/Oracles';
|
||||||
|
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||||
|
import { OracleDetails } from '../components/oracle';
|
||||||
|
import { useScrollToLocation } from '../../../hooks/scroll-to-location';
|
||||||
|
import filter from 'recursive-key-filter';
|
||||||
|
|
||||||
|
const Oracles = () => {
|
||||||
|
const { data, loading } = useExplorerOracleSpecsQuery();
|
||||||
|
|
||||||
|
useDocumentTitle(['Oracles']);
|
||||||
|
useScrollToLocation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<RouteTitle data-testid="oracle-specs-heading">{t('Oracles')}</RouteTitle>
|
||||||
|
{loading ? <Loader /> : null}
|
||||||
|
{data?.oracleSpecsConnection?.edges
|
||||||
|
? data.oracleSpecsConnection.edges.map((o) => {
|
||||||
|
const id = o?.node.dataSourceSpec.spec.id;
|
||||||
|
if (!id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div id={id} key={id} className="mb-10">
|
||||||
|
<OracleDetails
|
||||||
|
id={id}
|
||||||
|
dataSource={o?.node}
|
||||||
|
dataConnection={o?.node}
|
||||||
|
/>
|
||||||
|
<details>
|
||||||
|
<summary className="pointer">JSON</summary>
|
||||||
|
<SyntaxHighlighter data={filter(o, ['__typename'])} />
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: null}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Oracles;
|
49
apps/explorer/src/app/routes/oracles/id/index.tsx
Normal file
49
apps/explorer/src/app/routes/oracles/id/index.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { RouteTitle } from '../../../components/route-title';
|
||||||
|
import { RenderFetched } from '../../../components/render-fetched';
|
||||||
|
import { t, truncateByChars } from '@vegaprotocol/react-helpers';
|
||||||
|
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { useExplorerOracleSpecByIdQuery } from '../__generated__/Oracles';
|
||||||
|
import { OracleDetails } from '../components/oracle';
|
||||||
|
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import filter from 'recursive-key-filter';
|
||||||
|
import { TruncateInline } from '../../../components/truncate/truncate';
|
||||||
|
|
||||||
|
export const Oracle = () => {
|
||||||
|
const { id } = useParams<{ id: string }>();
|
||||||
|
|
||||||
|
useDocumentTitle(['Oracle', `Oracle #${truncateByChars(id || '1', 5, 5)}`]);
|
||||||
|
|
||||||
|
const { data, error, loading } = useExplorerOracleSpecByIdQuery({
|
||||||
|
variables: {
|
||||||
|
id: id || '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<RouteTitle data-testid="block-header">
|
||||||
|
{t(`Oracle `)}
|
||||||
|
<TruncateInline startChars={5} endChars={5} text={id || '1'} />
|
||||||
|
</RouteTitle>
|
||||||
|
<RenderFetched error={error} loading={loading}>
|
||||||
|
{data?.oracleSpec ? (
|
||||||
|
<div id={id} key={id} className="mb-10">
|
||||||
|
<OracleDetails
|
||||||
|
id={id || ''}
|
||||||
|
dataSource={data?.oracleSpec}
|
||||||
|
dataConnection={data?.oracleSpec}
|
||||||
|
showBroadcasts={true}
|
||||||
|
/>
|
||||||
|
<details>
|
||||||
|
<summary className="pointer">JSON</summary>
|
||||||
|
<SyntaxHighlighter data={filter(data, ['__typename'])} />
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<span></span>
|
||||||
|
)}
|
||||||
|
</RenderFetched>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
@ -1,45 +1,7 @@
|
|||||||
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
import { Outlet } from 'react-router-dom';
|
||||||
import { RouteTitle } from '../../components/route-title';
|
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
|
||||||
import { useExplorerOracleSpecsQuery } from './__generated__/Oracles';
|
|
||||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
|
||||||
import { OracleDetails } from './components/oracle';
|
|
||||||
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
|
||||||
import filter from 'recursive-key-filter';
|
|
||||||
|
|
||||||
const Oracles = () => {
|
const OraclePage = () => {
|
||||||
const { data, loading } = useExplorerOracleSpecsQuery();
|
return <Outlet />;
|
||||||
|
|
||||||
useDocumentTitle(['Oracles']);
|
|
||||||
useScrollToLocation();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section>
|
|
||||||
<RouteTitle data-testid="oracle-specs-heading">{t('Oracles')}</RouteTitle>
|
|
||||||
{loading ? <Loader /> : null}
|
|
||||||
{data?.oracleSpecsConnection?.edges
|
|
||||||
? data.oracleSpecsConnection.edges.map((o) => {
|
|
||||||
const id = o?.node.dataSourceSpec.spec.id;
|
|
||||||
if (!id) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div id={id} key={id} className="mb-10 cursor-pointer">
|
|
||||||
<OracleDetails
|
|
||||||
id={id}
|
|
||||||
dataSource={o?.node}
|
|
||||||
dataConnection={o?.node}
|
|
||||||
/>
|
|
||||||
<details>
|
|
||||||
<summary className="pointer">JSON</summary>
|
|
||||||
<SyntaxHighlighter data={filter(o, ['__typename'])} />
|
|
||||||
</details>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
: null}
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Oracles;
|
export default OraclePage;
|
||||||
|
@ -3,7 +3,9 @@ import BlockPage from './blocks';
|
|||||||
import Governance from './governance';
|
import Governance from './governance';
|
||||||
import Home from './home';
|
import Home from './home';
|
||||||
import Markets from './markets';
|
import Markets from './markets';
|
||||||
import Oracles from './oracles';
|
import OraclePage from './oracles';
|
||||||
|
import Oracles from './oracles/home';
|
||||||
|
import { Oracle } from './oracles/id';
|
||||||
import Party from './parties';
|
import Party from './parties';
|
||||||
import { Parties } from './parties/home';
|
import { Parties } from './parties/home';
|
||||||
import { Party as PartySingle } from './parties/id';
|
import { Party as PartySingle } from './parties/id';
|
||||||
@ -85,17 +87,6 @@ const marketsRoutes = flags.markets
|
|||||||
]
|
]
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const oraclesRoutes = flags.oracles
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
path: Routes.ORACLES,
|
|
||||||
name: 'Oracles',
|
|
||||||
text: t('Oracles'),
|
|
||||||
element: <Oracles />,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const networkParametersRoutes = flags.networkParameters
|
const networkParametersRoutes = flags.networkParameters
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
@ -161,12 +152,27 @@ const routerConfig = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: Routes.ORACLES,
|
||||||
|
name: 'Oracles',
|
||||||
|
text: t('Oracles'),
|
||||||
|
element: <OraclePage />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
index: true,
|
||||||
|
element: <Oracles />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':id',
|
||||||
|
element: <Oracle />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
...partiesRoutes,
|
...partiesRoutes,
|
||||||
...assetsRoutes,
|
...assetsRoutes,
|
||||||
...genesisRoutes,
|
...genesisRoutes,
|
||||||
...governanceRoutes,
|
...governanceRoutes,
|
||||||
...marketsRoutes,
|
...marketsRoutes,
|
||||||
...oraclesRoutes,
|
|
||||||
...networkParametersRoutes,
|
...networkParametersRoutes,
|
||||||
...validators,
|
...validators,
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user