feat(explorer): data submission tx view (#2698)
This commit is contained in:
parent
7db2a58f9d
commit
a60379b40f
@ -0,0 +1,45 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { JSONOracleData, parseData } from './data-submission-json-oracle';
|
||||||
|
|
||||||
|
describe('JSONOracleData', () => {
|
||||||
|
it('renders a code block if there is a payload that is base64 encoded', () => {
|
||||||
|
const p = 'eyJwcmljZXMuRVRIOTkudmFsdWUiOiAiMTMwNTAwMDAwMCJ9';
|
||||||
|
const screen = render(<JSONOracleData payload={p} />);
|
||||||
|
expect(screen.getByTestId('json-code')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders an error if b64 decoding fails', () => {
|
||||||
|
const p = 'not-encoded';
|
||||||
|
const screen = render(<JSONOracleData payload={p} />);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.getByText('Awaiting Block Explorer transaction details')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Parse JSON oracle data', () => {
|
||||||
|
it('returns null for an invalid b64 string', () => {
|
||||||
|
expect(parseData('🤷')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null for a string that looks like an object', () => {
|
||||||
|
expect(parseData('{}')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null for null', () => {
|
||||||
|
expect(parseData(null as unknown as string)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a string for b64 encoded data', () => {
|
||||||
|
const res = parseData('dGVzdCA9IHRydWU=');
|
||||||
|
expect(typeof res).toEqual('string');
|
||||||
|
expect(res).toEqual('test = true');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a string for b64 encoded json, without any extra parsing', () => {
|
||||||
|
const res = parseData('eyJ0ZXN0Ijp0cnVlfQ==');
|
||||||
|
expect(typeof res).toEqual('string');
|
||||||
|
expect(res).toEqual('{"test":true}');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,40 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
interface JSONOracleDataProps {
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a JSON oracle. Given the shape could be any valid JSON,
|
||||||
|
* this doesn't try to do anything smart - it just renders the message
|
||||||
|
*/
|
||||||
|
export const JSONOracleData = ({ payload }: JSONOracleDataProps) => {
|
||||||
|
const decodedSubmission = parseData(payload);
|
||||||
|
|
||||||
|
if (!decodedSubmission) {
|
||||||
|
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<code data-testid="json-code">{decodedSubmission}</code>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely parses the JSON Oracle payload
|
||||||
|
*
|
||||||
|
* @param payload base64 encoded JSON
|
||||||
|
* @returns Object or null
|
||||||
|
*/
|
||||||
|
export function parseData(payload: string) {
|
||||||
|
try {
|
||||||
|
if (!payload || typeof payload !== 'string') {
|
||||||
|
throw new Error('Not a string');
|
||||||
|
}
|
||||||
|
return atob(payload);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { OpenOracleData, parseData } from './data-submission-open-oracle';
|
||||||
|
|
||||||
|
describe('OpenOracleData', () => {
|
||||||
|
it('renders a table if there is data', () => {
|
||||||
|
const p =
|
||||||
|
'eyJtZXNzYWdlcyI6IFsiMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA2M2M3ZTMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNGYxZjM4ZWEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjcwNzI2OTYzNjU3MzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNDI1NDQzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCJdLCAicHJpY2VzIjogeyJFVEgiOiIxMjMifSwgInNpZ25hdHVyZXMiOiBbIjB4N2U0Nzc2OWEyNzI5NzIwN2Q5ZTIyMmM3YTY2YjBlYzk3Njg4MWY3NmVkYjg5OGFhYzQ5OTRlZWYwOTc4MmI3NGUxMGE5MTJmZWQ1Y2E3NmFlN2U3NzVjOWZiOTBjZGE4ZjhkMDhlNzUyOTE1NzQ2ZTY2OGE1ZWM3OWRmOTZmNmQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDFjIl0sICJ0aW1lc3RhbXAiOiAiMTIzIn0=';
|
||||||
|
|
||||||
|
const screen = render(<OpenOracleData payload={p} />);
|
||||||
|
expect(screen.getByTestId('decoded-payload')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('ETH')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('123')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders an error if decoding fails', () => {
|
||||||
|
const p = 'not-encoded';
|
||||||
|
const screen = render(<OpenOracleData payload={p} />);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.getByText('Awaiting Block Explorer transaction details')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Parse Open oracle data', () => {
|
||||||
|
it('returns null for an invalid b64 string', () => {
|
||||||
|
expect(parseData('🤷')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null for a string that looks like an object', () => {
|
||||||
|
expect(parseData('{}')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null for null', () => {
|
||||||
|
expect(parseData(null as unknown as string)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a string for b64 encoded data', () => {
|
||||||
|
const res = parseData('dGVzdCA9IHRydWU=');
|
||||||
|
expect(res).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null if the parsed object does not look like te right shape', () => {
|
||||||
|
// Encoded: {"test":true}
|
||||||
|
const res = parseData('eyJ0ZXN0Ijp0cnVlfQ==');
|
||||||
|
expect(res).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns an object if the payload parses and looks fine', () => {
|
||||||
|
// Encoded: {"messages": [], "prices": {}, "signatures": [], "timestamp": "123"}
|
||||||
|
const res = parseData(
|
||||||
|
'eyJtZXNzYWdlcyI6IFtdLCAicHJpY2VzIjoge30sICJzaWduYXR1cmVzIjogW10sICJ0aW1lc3RhbXAiOiAiMTIzIn0='
|
||||||
|
);
|
||||||
|
expect(typeof res.prices).toEqual('object');
|
||||||
|
expect(Array.isArray(res.messages)).toBeTruthy();
|
||||||
|
expect(Array.isArray(res.signatures)).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,64 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import { NestedDataList } from '../../../nested-data-list';
|
||||||
|
import { OpenOraclePrices } from './open-oracle/open-oracle-prices';
|
||||||
|
|
||||||
|
interface OpenOracleDataProps {
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes Open Oracle data based on it's main parts:
|
||||||
|
* - messages
|
||||||
|
* - signatures
|
||||||
|
* - prices
|
||||||
|
*/
|
||||||
|
export const OpenOracleData = ({ payload }: OpenOracleDataProps) => {
|
||||||
|
const decodedSubmission = parseData(payload);
|
||||||
|
|
||||||
|
if (!decodedSubmission) {
|
||||||
|
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = decodedSubmission.timestamp;
|
||||||
|
const formattedDate = new Date(date * 1000).toLocaleString();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<span>{formattedDate}</span>
|
||||||
|
<code>
|
||||||
|
<OpenOraclePrices
|
||||||
|
prices={decodedSubmission.prices}
|
||||||
|
messages={decodedSubmission.messages}
|
||||||
|
signatures={decodedSubmission.signatures}
|
||||||
|
/>
|
||||||
|
</code>
|
||||||
|
<details data-testid="decoded-payload">
|
||||||
|
<summary>{t('Decoded payload')}</summary>
|
||||||
|
<NestedDataList data={decodedSubmission} />
|
||||||
|
</details>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely parses the Open Oracle payload
|
||||||
|
*
|
||||||
|
* @param payload base64 encoded JSON
|
||||||
|
* @returns Object or null
|
||||||
|
*/
|
||||||
|
export function parseData(payload: string) {
|
||||||
|
try {
|
||||||
|
if (!payload || typeof payload !== 'string') {
|
||||||
|
throw new Error('Not a string');
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = JSON.parse(atob(payload));
|
||||||
|
if (!res.prices || !res.messages || !res.signatures) {
|
||||||
|
throw new Error('Not an open oracle format message');
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { OpenOraclePrices } from './open-oracle-prices';
|
||||||
|
import type { Price } from './open-oracle-prices';
|
||||||
|
|
||||||
|
describe('OpenOraclePrices', () => {
|
||||||
|
it('Will not render with no prices', () => {
|
||||||
|
const p = undefined as unknown as Price;
|
||||||
|
const m: string[] = [];
|
||||||
|
const s: string[] = [];
|
||||||
|
const screen = render(
|
||||||
|
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Will not render with no messages', () => {
|
||||||
|
const m = undefined as unknown as string[];
|
||||||
|
const p: Price = {};
|
||||||
|
const s: string[] = [];
|
||||||
|
const screen = render(
|
||||||
|
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will not render with no signatures', () => {
|
||||||
|
const s = undefined as unknown as string[];
|
||||||
|
const m: string[] = [];
|
||||||
|
const p: Price = {};
|
||||||
|
const screen = render(
|
||||||
|
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will not render with mismatched prices/signatures', () => {
|
||||||
|
const p: Price = { ETH: '123' };
|
||||||
|
const m = ['0x123', '0x456'];
|
||||||
|
const s: string[] = [];
|
||||||
|
const screen = render(
|
||||||
|
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will not render with mismatched signatures and messages', () => {
|
||||||
|
const p: Price = { ETH: '123', BTC: '12' };
|
||||||
|
const s = ['0xcac', '0xb33f'];
|
||||||
|
const m = ['0x1204o42c', '0xb3ddd3f', '0x9999'];
|
||||||
|
|
||||||
|
const screen = render(
|
||||||
|
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders a table when there are prices and signatures and messages', () => {
|
||||||
|
const p: Price = { ETH: '123', BTC: '12' };
|
||||||
|
const s = ['0xcac', '0xb33f'];
|
||||||
|
const m = ['0x120442c', '0xb3ddd3f'];
|
||||||
|
|
||||||
|
const screen = render(
|
||||||
|
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||||
|
);
|
||||||
|
expect(screen.getByTestId('openoracleprices')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// Table headings
|
||||||
|
expect(screen.getByText('Asset')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Price')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Signature')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Message')).toBeInTheDocument();
|
||||||
|
// Disabled - see vegaprotocol/frontend-monorepo#/2726
|
||||||
|
// expect(screen.getByText('Signer')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// One row per asset
|
||||||
|
expect(screen.getByText('ETH')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('123')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('0xcac')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('0xb33f')).toBeInTheDocument();
|
||||||
|
// Does not test signer element for this row
|
||||||
|
|
||||||
|
expect(screen.getByText('BTC')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('12')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('0x120442c')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('0xb3ddd3f')).toBeInTheDocument();
|
||||||
|
// Does not test signer element for this row
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,132 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import { CopyWithTooltip } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { TableRow } from '../../../../table';
|
||||||
|
import { TruncateInline } from '../../../../truncate/truncate';
|
||||||
|
import { utils } from 'ethers';
|
||||||
|
|
||||||
|
export type Price = {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface OpenOraclePricesProps {
|
||||||
|
prices: Price;
|
||||||
|
signatures: string[];
|
||||||
|
messages: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open Oracle price table, showing the entries in this
|
||||||
|
* decoded message
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* - Signer is derived by recovering the address from the
|
||||||
|
* signature and the message. This is currently disabled
|
||||||
|
* as the implementation is incorrect
|
||||||
|
*/
|
||||||
|
export function OpenOraclePrices({
|
||||||
|
prices,
|
||||||
|
messages,
|
||||||
|
signatures,
|
||||||
|
}: OpenOraclePricesProps) {
|
||||||
|
if (
|
||||||
|
!prices ||
|
||||||
|
!messages ||
|
||||||
|
!signatures ||
|
||||||
|
Object.keys(prices).length !== messages.length ||
|
||||||
|
signatures.length !== messages.length
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<table data-testid="openoracleprices">
|
||||||
|
<thead>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<th>{t('Asset')}</th>
|
||||||
|
<th className="text-right">{t('Price')}</th>
|
||||||
|
<th>{t('Signature')}</th>
|
||||||
|
<th>{t('Message')}</th>
|
||||||
|
{/* <th>{t('Signer')}</th> */}
|
||||||
|
</TableRow>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{Object.keys(prices).map((k: string, i: number) => {
|
||||||
|
if (k && prices[k]) {
|
||||||
|
const message = messages[i];
|
||||||
|
const signature = signatures[i];
|
||||||
|
return (
|
||||||
|
<OpenOraclePrice
|
||||||
|
key={`price-${i}`}
|
||||||
|
asset={k}
|
||||||
|
value={prices[k]}
|
||||||
|
message={message}
|
||||||
|
signature={signature}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpenOraclePriceProps = {
|
||||||
|
asset: string;
|
||||||
|
value: string;
|
||||||
|
message: string;
|
||||||
|
signature: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function OpenOraclePrice({
|
||||||
|
asset,
|
||||||
|
value,
|
||||||
|
signature,
|
||||||
|
message,
|
||||||
|
}: OpenOraclePriceProps) {
|
||||||
|
// const addr = getAddressFromMessageAndSignature(message, signature);
|
||||||
|
return (
|
||||||
|
<TableRow modifier="bordered" key={`${asset}`}>
|
||||||
|
<td className="px-4">{asset}</td>
|
||||||
|
<td className="px-4 text-right">{value}</td>
|
||||||
|
<td className="px-4">
|
||||||
|
<CopyWithTooltip text={signature}>
|
||||||
|
<button>
|
||||||
|
<TruncateInline text={signature} startChars={5} endChars={5} />
|
||||||
|
</button>
|
||||||
|
</CopyWithTooltip>
|
||||||
|
</td>
|
||||||
|
<td className="px-4">
|
||||||
|
<CopyWithTooltip text={message}>
|
||||||
|
<button>
|
||||||
|
<TruncateInline text={message} startChars={5} endChars={5} />
|
||||||
|
</button>
|
||||||
|
</CopyWithTooltip>
|
||||||
|
</td>
|
||||||
|
{/*<td className="px-4">
|
||||||
|
<CopyWithTooltip text={message}>
|
||||||
|
<button>
|
||||||
|
<TruncateInline text={addr} startChars={5} endChars={5} />
|
||||||
|
</button>
|
||||||
|
</CopyWithTooltip>
|
||||||
|
</td> */}
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAddressFromMessageAndSignature(
|
||||||
|
message: string,
|
||||||
|
signature: string
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const m = utils.hashMessage(utils.arrayify(utils.keccak256(message)));
|
||||||
|
const s = utils.splitSignature(
|
||||||
|
signature.slice(0, 130) + signature.slice(-2)
|
||||||
|
);
|
||||||
|
|
||||||
|
return utils.recoverAddress(m, s);
|
||||||
|
} catch (e) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||||
|
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||||
|
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||||
|
import { TableWithTbody } from '../../table';
|
||||||
|
import type { components } from '../../../../types/explorer';
|
||||||
|
import { OpenOracleData } from './oracle-data/data-submission-open-oracle';
|
||||||
|
import { JSONOracleData } from './oracle-data/data-submission-json-oracle';
|
||||||
|
|
||||||
|
export type OracleSubmissionSource =
|
||||||
|
components['schemas']['OracleDataSubmissionOracleSource'];
|
||||||
|
|
||||||
|
interface TxDetailsDataSubmissionProps {
|
||||||
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
|
pubKey: string | undefined;
|
||||||
|
blockData: TendermintBlocksResponse | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Someone cancelled an order
|
||||||
|
*/
|
||||||
|
export const TxDetailsDataSubmission = ({
|
||||||
|
txData,
|
||||||
|
pubKey,
|
||||||
|
blockData,
|
||||||
|
}: TxDetailsDataSubmissionProps) => {
|
||||||
|
if (!txData || !txData.command.oracleDataSubmission) {
|
||||||
|
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const type: OracleSubmissionSource =
|
||||||
|
txData.command.oracleDataSubmission.source;
|
||||||
|
if (!type) {
|
||||||
|
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = txData.command.oracleDataSubmission.payload;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TableWithTbody className="mb-8">
|
||||||
|
<TxDetailsShared
|
||||||
|
txData={txData}
|
||||||
|
pubKey={pubKey}
|
||||||
|
blockData={blockData}
|
||||||
|
/>
|
||||||
|
</TableWithTbody>
|
||||||
|
{type === 'ORACLE_SOURCE_OPEN_ORACLE' ? (
|
||||||
|
<OpenOracleData payload={payload} />
|
||||||
|
) : (
|
||||||
|
<JSONOracleData payload={payload} />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -19,6 +19,7 @@ import { TxDetailsUndelegate } from './tx-undelegation';
|
|||||||
import { TxDetailsLiquiditySubmission } from './tx-liquidity-submission';
|
import { TxDetailsLiquiditySubmission } from './tx-liquidity-submission';
|
||||||
import { TxDetailsLiquidityAmendment } from './tx-liquidity-amend';
|
import { TxDetailsLiquidityAmendment } from './tx-liquidity-amend';
|
||||||
import { TxDetailsLiquidityCancellation } from './tx-liquidity-cancel';
|
import { TxDetailsLiquidityCancellation } from './tx-liquidity-cancel';
|
||||||
|
import { TxDetailsDataSubmission } from './tx-data-submission';
|
||||||
|
|
||||||
interface TxDetailsWrapperProps {
|
interface TxDetailsWrapperProps {
|
||||||
txData: BlockExplorerTransactionResult | undefined;
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
@ -82,6 +83,8 @@ function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
|
|||||||
switch (txData.type) {
|
switch (txData.type) {
|
||||||
case 'Submit Order':
|
case 'Submit Order':
|
||||||
return TxDetailsOrder;
|
return TxDetailsOrder;
|
||||||
|
case 'Submit Oracle Data':
|
||||||
|
return TxDetailsDataSubmission;
|
||||||
case 'Cancel Order':
|
case 'Cancel Order':
|
||||||
return TxDetailsOrderCancel;
|
return TxDetailsOrderCancel;
|
||||||
case 'Amend Order':
|
case 'Amend Order':
|
||||||
|
Loading…
Reference in New Issue
Block a user