diff --git a/apps/explorer/src/app/components/txs/tx-transfer.spec.tsx b/apps/explorer/src/app/components/txs/tx-transfer.spec.tsx index 4f5e5f29e..3decc9a7a 100644 --- a/apps/explorer/src/app/components/txs/tx-transfer.spec.tsx +++ b/apps/explorer/src/app/components/txs/tx-transfer.spec.tsx @@ -81,6 +81,7 @@ describe('TxDetailsTransfer', () => { hash: 'test', submitter: 'e1943eea46fed576cf2be42972f3c5515ad3d0ac7ac013f56677c12a53a1b3ed', + block: '100', command: { nonce: '5188810881378065222', blockHeight: '14951513', diff --git a/apps/explorer/src/app/routes/oracles/OraclesForMarkets.graphql b/apps/explorer/src/app/routes/oracles/OraclesForMarkets.graphql index 3412843d8..b1646f958 100644 --- a/apps/explorer/src/app/routes/oracles/OraclesForMarkets.graphql +++ b/apps/explorer/src/app/routes/oracles/OraclesForMarkets.graphql @@ -89,7 +89,7 @@ fragment ExplorerOracleDataSourceSpec on ExternalDataSourceSpec { } query ExplorerOracleFormMarkets { - marketsConnection { + marketsConnection(includeSettled: false, pagination: { first: 20 }) { edges { node { ...ExplorerOracleForMarketsMarket @@ -102,7 +102,7 @@ query ExplorerOracleFormMarkets { dataSourceSpec { ...ExplorerOracleDataSourceSpec } - dataConnection(pagination: { last: 1 }) { + dataConnection(pagination: { first: 1 }) { edges { node { externalData { diff --git a/apps/explorer/src/app/routes/oracles/__generated__/OraclesForMarkets.ts b/apps/explorer/src/app/routes/oracles/__generated__/OraclesForMarkets.ts index 9eafd558b..94ba581d0 100644 --- a/apps/explorer/src/app/routes/oracles/__generated__/OraclesForMarkets.ts +++ b/apps/explorer/src/app/routes/oracles/__generated__/OraclesForMarkets.ts @@ -120,7 +120,7 @@ export const ExplorerOracleDataSourceSpecFragmentDoc = gql` `; export const ExplorerOracleFormMarketsDocument = gql` query ExplorerOracleFormMarkets { - marketsConnection { + marketsConnection(includeSettled: false, pagination: {first: 20}) { edges { node { ...ExplorerOracleForMarketsMarket @@ -133,7 +133,7 @@ export const ExplorerOracleFormMarketsDocument = gql` dataSourceSpec { ...ExplorerOracleDataSourceSpec } - dataConnection(pagination: {last: 1}) { + dataConnection(pagination: {first: 1}) { edges { node { externalData { diff --git a/apps/explorer/src/app/routes/oracles/components/oracle-eth-source.tsx b/apps/explorer/src/app/routes/oracles/components/oracle-eth-source.tsx index 6a8d1d3c1..696f8efe5 100644 --- a/apps/explorer/src/app/routes/oracles/components/oracle-eth-source.tsx +++ b/apps/explorer/src/app/routes/oracles/components/oracle-eth-source.tsx @@ -6,6 +6,11 @@ import { } from '../../../components/links/external-explorer-link/external-explorer-link'; import { getExternalChainLabel } from '@vegaprotocol/environment'; import { t } from 'i18next'; +import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit'; +import isArray from 'lodash/isArray'; +import type { components } from '../../../../types/explorer'; + +type Normalisers = components['schemas']['vegaNormaliser'][]; interface OracleDetailsEthSourceProps { sourceType: SourceType; @@ -34,21 +39,117 @@ export function OracleEthSource({ const chainLabel = getExternalChainLabel(chain); + const abi = prepareOracleSpecField(sourceType?.sourceType?.abi); + const args = prepareOracleSpecField(sourceType?.sourceType?.args); + const normalisers = serialiseNormalisers(sourceType.sourceType.normalisers); + return ( - + {chainLabel} {t('Contract')} - - - {sourceType.sourceType.method} +
+ + + + {sourceType.sourceType.method} + + + {args && ( + <> +

{t('Arguments')}

+
+ +
+ + )} + + {abi && ( + <> +

{t('ABI')}

+
+ +
+ + )} + + {normalisers && ( + <> +

{t('Normalisers')}

+
+ +
+ + )} +
); } + +// Constant to define the absence of a valid string from the Oracle Spec fields +const NO_DATA = false; + +/** + * The ABI and args are stored as either a (JSON escaped, probably) string + * or array of strings. Given that OracleEthSource is simply throwing the + * data in to a SyntaxHighlighter, we don't really care about the format, + * so this function will just try to parse the data and return it as a string. + * + * @param abi + * @returns + */ +export function prepareOracleSpecField( + specField?: string[] | null +): string | false { + if (!specField) { + return NO_DATA; + } + + try { + if (isArray(specField)) { + return JSON.parse(specField.join('')); + } else { + return JSON.parse(specField); + } + } catch (e) { + return NO_DATA; + } +} + +/** + * Similar to prepareOracleSpecField above, but processes an array of normaliser objects + * removing the __typename and returning a serialised array of normalisers for + * SyntaxHighlighter + * + * @param normalisers + * @returns + */ +export function serialiseNormalisers( + normalisers?: Normalisers | null +): Normalisers | false { + if (!normalisers) { + return NO_DATA; + } + + try { + return normalisers.map((normaliser) => { + return { + name: normaliser.name, + expression: normaliser.expression, + }; + }); + } catch (e) { + return NO_DATA; + } +} diff --git a/apps/explorer/src/app/routes/oracles/components/oracle-filter.spec.tsx b/apps/explorer/src/app/routes/oracles/components/oracle-filter.spec.tsx index 5bc9c78b5..72a2ebeb9 100644 --- a/apps/explorer/src/app/routes/oracles/components/oracle-filter.spec.tsx +++ b/apps/explorer/src/app/routes/oracles/components/oracle-filter.spec.tsx @@ -1,38 +1,9 @@ import { render } from '@testing-library/react'; import { OracleFilter } from './oracle-filter'; import type { ExplorerOracleDataSourceFragment } from '../__generated__/Oracles'; -import { - ConditionOperator, - DataSourceSpecStatus, - PropertyKeyType, -} from '@vegaprotocol/types'; +import { ConditionOperator, DataSourceSpecStatus } from '@vegaprotocol/types'; import type { Condition } from '@vegaprotocol/types'; -type Spec = - ExplorerOracleDataSourceFragment['dataSourceSpec']['spec']['data']['sourceType']; - -const mockExternalSpec: Spec = { - sourceType: { - __typename: 'DataSourceSpecConfiguration', - filters: [ - { - __typename: 'Filter', - key: { - type: PropertyKeyType.TYPE_INTEGER, - name: 'testKey', - }, - conditions: [ - { - __typename: 'Condition', - value: 'testValue', - operator: ConditionOperator.OPERATOR_EQUALS, - }, - ], - }, - ], - }, -}; - function renderComponent(data: ExplorerOracleDataSourceFragment) { return ; } @@ -50,31 +21,6 @@ describe('Oracle Filter view', () => { expect(res.container).toBeEmptyDOMElement(); }); - it('Renders filters if type is DataSourceSpecConfiguration', () => { - const res = render( - renderComponent({ - dataSourceSpec: { - spec: { - id: 'irrelevant-test-data', - createdAt: 'irrelevant-test-data', - status: DataSourceSpecStatus.STATUS_ACTIVE, - data: { - sourceType: mockExternalSpec, - }, - }, - }, - dataConnection: { - edges: [], - }, - }) - ); - - // Renders a comprehensible summary of key = value - expect(res.getByText('testKey')).toBeInTheDocument(); - expect(res.getByText('=')).toBeInTheDocument(); - expect(res.getByText('testValue')).toBeInTheDocument(); - }); - it('Renders conditions if type is DataSourceSpecConfigurationTime', () => { const res = render( renderComponent({ @@ -136,7 +82,7 @@ describe('Oracle Filter view', () => { }) ); - // This should never happen, but for coverage sake we test that it does this + // This should never happen, but for coverage we test that it does this const ul = res.getByRole('list'); expect(ul).toBeInTheDocument(); expect(ul).toBeEmptyDOMElement(); diff --git a/apps/explorer/src/app/routes/oracles/components/oracle-filter.tsx b/apps/explorer/src/app/routes/oracles/components/oracle-filter.tsx index c9608e2ff..cc63d7604 100644 --- a/apps/explorer/src/app/routes/oracles/components/oracle-filter.tsx +++ b/apps/explorer/src/app/routes/oracles/components/oracle-filter.tsx @@ -1,5 +1,8 @@ import type { ExplorerOracleDataSourceFragment } from '../__generated__/Oracles'; -import { OracleSpecInternalTimeTrigger } from './oracle-spec/internal-time-trigger'; +import { + OracleSpecInternalTimeTrigger, + TimeTrigger, +} from './oracle-spec/internal-time-trigger'; import { OracleSpecCondition } from './oracle-spec/condition'; import { getCharacterForOperator } from './oracle-spec/operator'; @@ -11,7 +14,7 @@ interface OracleFilterProps { * Shows the conditions that this oracle is using to filter * data sources, as a list. * - * Renders nothing if there is no data (which will frequently) + * Renders nothing if there is no data (which will frequently * be the case) and if there is data, currently renders a simple * JSON view. */ @@ -21,6 +24,7 @@ export function OracleFilter({ data }: OracleFilterProps) { } const s = data.dataSourceSpec.spec.data.sourceType.sourceType; + if (s.__typename === 'DataSourceSpecConfigurationTime' && s.conditions) { return (