Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5a34cb636 |
@@ -4,6 +4,7 @@ import { useExplorerAssetQuery } from './__generated__/Asset';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import type { ComponentProps } from 'react';
|
import type { ComponentProps } from 'react';
|
||||||
|
import Hash from '../hash';
|
||||||
|
|
||||||
export type AssetLinkProps = Partial<ComponentProps<typeof Link>> & {
|
export type AssetLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -27,7 +28,7 @@ const AssetLink = ({ id, ...props }: AssetLinkProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Link className="underline" {...props} to={`/${Routes.ASSETS}#${id}`}>
|
<Link className="underline" {...props} to={`/${Routes.ASSETS}#${id}`}>
|
||||||
{label}
|
<Hash text={label} />
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Routes } from '../../../routes/route-names';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import type { ComponentProps } from 'react';
|
import type { ComponentProps } from 'react';
|
||||||
|
import Hash from '../hash';
|
||||||
|
|
||||||
export type BlockLinkProps = Partial<ComponentProps<typeof Link>> & {
|
export type BlockLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||||
height: string;
|
height: string;
|
||||||
@@ -11,7 +12,7 @@ export type BlockLinkProps = Partial<ComponentProps<typeof Link>> & {
|
|||||||
const BlockLink = ({ height, ...props }: BlockLinkProps) => {
|
const BlockLink = ({ height, ...props }: BlockLinkProps) => {
|
||||||
return (
|
return (
|
||||||
<Link className="underline" {...props} to={`/${Routes.BLOCKS}/${height}`}>
|
<Link className="underline" {...props} to={`/${Routes.BLOCKS}/${height}`}>
|
||||||
{height}
|
<Hash text={height} />
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { DATA_SOURCES } from '../../../config';
|
import { DATA_SOURCES } from '../../../config';
|
||||||
|
import Hash from '../hash';
|
||||||
|
|
||||||
export enum EthExplorerLinkTypes {
|
export enum EthExplorerLinkTypes {
|
||||||
block = 'block',
|
block = 'block',
|
||||||
@@ -27,7 +28,7 @@ export const EthExplorerLink = ({
|
|||||||
{...props}
|
{...props}
|
||||||
href={link}
|
href={link}
|
||||||
>
|
>
|
||||||
{id}
|
<Hash text={id} />
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export type HashProps = {
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple component that ensures long text things like hashes
|
||||||
|
* are broken when they need to wrap. This will remove the need
|
||||||
|
* for a lot of the overflow scrolling that currently exists.
|
||||||
|
*/
|
||||||
|
const Hash = ({ text }: HashProps) => {
|
||||||
|
return (
|
||||||
|
<code className="break-all font-mono" style={{ wordWrap: 'break-word' }}>
|
||||||
|
{text}
|
||||||
|
</code>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Hash;
|
||||||
@@ -4,6 +4,7 @@ import { Link } from 'react-router-dom';
|
|||||||
|
|
||||||
import type { ComponentProps } from 'react';
|
import type { ComponentProps } from 'react';
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import Hash from '../hash';
|
||||||
|
|
||||||
export type MarketLinkProps = Partial<ComponentProps<typeof Link>> & {
|
export type MarketLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -35,7 +36,8 @@ const MarketLink = ({
|
|||||||
<span role="img" aria-label="Unknown market" className="img">
|
<span role="img" aria-label="Unknown market" className="img">
|
||||||
⚠️ {t('Invalid market')}
|
⚠️ {t('Invalid market')}
|
||||||
</span>
|
</span>
|
||||||
{id}
|
|
||||||
|
<Hash text={id} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -55,7 +57,7 @@ const MarketLink = ({
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<Link className="underline" {...props} to={`/${Routes.MARKETS}#${id}`}>
|
<Link className="underline" {...props} to={`/${Routes.MARKETS}#${id}`}>
|
||||||
{id}
|
<Hash text={id} />
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useExplorerNodeQuery } from './__generated__/Node';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import type { ComponentProps } from 'react';
|
import type { ComponentProps } from 'react';
|
||||||
|
import Hash from '../hash';
|
||||||
|
|
||||||
export type NodeLinkProps = Partial<ComponentProps<typeof Link>> & {
|
export type NodeLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -22,7 +23,7 @@ const NodeLink = ({ id, ...props }: NodeLinkProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Link className="underline" {...props} to={`/${Routes.VALIDATORS}#${id}`}>
|
<Link className="underline" {...props} to={`/${Routes.VALIDATORS}#${id}`}>
|
||||||
<code>{label}</code>
|
<Hash text={label} />
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Routes } from '../../../routes/route-names';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import type { ComponentProps } from 'react';
|
import type { ComponentProps } from 'react';
|
||||||
|
import Hash from '../hash';
|
||||||
|
|
||||||
export type OracleLinkProps = Partial<ComponentProps<typeof Link>> & {
|
export type OracleLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -14,7 +15,7 @@ const OracleLink = ({ id, ...props }: OracleLinkProps) => {
|
|||||||
{...props}
|
{...props}
|
||||||
to={`/${Routes.ORACLES}/${id}`}
|
to={`/${Routes.ORACLES}/${id}`}
|
||||||
>
|
>
|
||||||
{id}
|
<Hash text={id} />
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Routes } from '../../../routes/route-names';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import type { ComponentProps } from 'react';
|
import type { ComponentProps } from 'react';
|
||||||
|
import Hash from '../hash';
|
||||||
|
|
||||||
export type PartyLinkProps = Partial<ComponentProps<typeof Link>> & {
|
export type PartyLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -14,7 +15,7 @@ const PartyLink = ({ id, ...props }: PartyLinkProps) => {
|
|||||||
{...props}
|
{...props}
|
||||||
to={`/${Routes.PARTIES}/${id}`}
|
to={`/${Routes.PARTIES}/${id}`}
|
||||||
>
|
>
|
||||||
{id}
|
<Hash text={id} />
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ describe('Proposal link component', () => {
|
|||||||
expect(res.getByText('123')).toBeInTheDocument();
|
expect(res.getByText('123')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders the ID with an emoji on error', async () => {
|
it('Renders the ID on error', async () => {
|
||||||
const mock = {
|
const mock = {
|
||||||
request: {
|
request: {
|
||||||
query: ExplorerProposalDocument,
|
query: ExplorerProposalDocument,
|
||||||
@@ -37,9 +37,6 @@ describe('Proposal link component', () => {
|
|||||||
const res = render(renderComponent('456', [mock]));
|
const res = render(renderComponent('456', [mock]));
|
||||||
// The ID
|
// The ID
|
||||||
expect(res.getByText('456')).toBeInTheDocument();
|
expect(res.getByText('456')).toBeInTheDocument();
|
||||||
|
|
||||||
// The emoji
|
|
||||||
expect(await res.findByRole('img')).toBeInTheDocument();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders the proposal title when the query returns a result', async () => {
|
it('Renders the proposal title when the query returns a result', async () => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useExplorerProposalQuery } from './__generated__/Proposal';
|
import { useExplorerProposalQuery } from './__generated__/Proposal';
|
||||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import { ENV } from '../../../config/env';
|
import { ENV } from '../../../config/env';
|
||||||
|
import Hash from '../hash';
|
||||||
export type ProposalLinkProps = {
|
export type ProposalLinkProps = {
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
@@ -17,7 +18,11 @@ const ProposalLink = ({ id }: ProposalLinkProps) => {
|
|||||||
const base = ENV.dataSources.governanceUrl;
|
const base = ENV.dataSources.governanceUrl;
|
||||||
const label = data?.proposal?.rationale.title || id;
|
const label = data?.proposal?.rationale.title || id;
|
||||||
|
|
||||||
return <ExternalLink href={`${base}/proposals/${id}`}>{label}</ExternalLink>;
|
return (
|
||||||
|
<ExternalLink href={`${base}/proposals/${id}`}>
|
||||||
|
<Hash text={label} />
|
||||||
|
</ExternalLink>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProposalLink;
|
export default ProposalLink;
|
||||||
|
|||||||
+10
-4
@@ -63,15 +63,21 @@ describe('Chain Event: Builtin asset deposit', () => {
|
|||||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
const partyLink = screen.getByText(`${fullMock.partyId}`);
|
const partyLink = screen.getByText(`${fullMock.partyId}`);
|
||||||
expect(partyLink).toBeInTheDocument();
|
expect(partyLink).toBeInTheDocument();
|
||||||
expect(partyLink.tagName).toEqual('A');
|
if (!partyLink.parentElement) {
|
||||||
expect(partyLink.getAttribute('href')).toEqual(
|
throw new Error('Party link does not exist');
|
||||||
|
}
|
||||||
|
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/parties/${fullMock.partyId}`
|
`/parties/${fullMock.partyId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
expect(assetLink).toBeInTheDocument();
|
expect(assetLink).toBeInTheDocument();
|
||||||
expect(assetLink.tagName).toEqual('A');
|
if (!assetLink.parentElement) {
|
||||||
expect(assetLink.getAttribute('href')).toEqual(
|
throw new Error('Asset link does not exist');
|
||||||
|
}
|
||||||
|
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/assets#${fullMock.vegaAssetId}`
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
+10
-4
@@ -69,15 +69,21 @@ describe('Chain Event: Builtin asset withdrawal', () => {
|
|||||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
const partyLink = screen.getByText(`${fullMock.partyId}`);
|
const partyLink = screen.getByText(`${fullMock.partyId}`);
|
||||||
expect(partyLink).toBeInTheDocument();
|
expect(partyLink).toBeInTheDocument();
|
||||||
expect(partyLink.tagName).toEqual('A');
|
if (!partyLink.parentElement) {
|
||||||
expect(partyLink.getAttribute('href')).toEqual(
|
throw new Error('Party link does not exist');
|
||||||
|
}
|
||||||
|
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/parties/${fullMock.partyId}`
|
`/parties/${fullMock.partyId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
expect(assetLink).toBeInTheDocument();
|
expect(assetLink).toBeInTheDocument();
|
||||||
expect(assetLink.tagName).toEqual('A');
|
if (!assetLink.parentElement) {
|
||||||
expect(assetLink.getAttribute('href')).toEqual(
|
throw new Error('Asset link does not exist');
|
||||||
|
}
|
||||||
|
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/assets#${fullMock.vegaAssetId}`
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
+5
-2
@@ -60,8 +60,11 @@ describe('Chain Event: ERC20 Asset Delist', () => {
|
|||||||
|
|
||||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
expect(assetLink).toBeInTheDocument();
|
expect(assetLink).toBeInTheDocument();
|
||||||
expect(assetLink.tagName).toEqual('A');
|
if (!assetLink.parentElement) {
|
||||||
expect(assetLink.getAttribute('href')).toEqual(
|
throw new Error('Asset link does not exist');
|
||||||
|
}
|
||||||
|
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/assets#${fullMock.vegaAssetId}`
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
+9
-3
@@ -76,14 +76,20 @@ describe('Chain Event: ERC20 Asset limits updated', () => {
|
|||||||
expect(screen.getByText(t('Vega asset'))).toBeInTheDocument();
|
expect(screen.getByText(t('Vega asset'))).toBeInTheDocument();
|
||||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
expect(assetLink).toBeInTheDocument();
|
expect(assetLink).toBeInTheDocument();
|
||||||
expect(assetLink.tagName).toEqual('A');
|
if (!assetLink.parentElement) {
|
||||||
expect(assetLink.getAttribute('href')).toEqual(
|
throw new Error('Asset link does not exist');
|
||||||
|
}
|
||||||
|
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/assets#${fullMock.vegaAssetId}`
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText(t('ERC20 asset'))).toBeInTheDocument();
|
expect(screen.getByText(t('ERC20 asset'))).toBeInTheDocument();
|
||||||
const ethLink = screen.getByText(`${fullMock.sourceEthereumAddress}`);
|
const ethLink = screen.getByText(`${fullMock.sourceEthereumAddress}`);
|
||||||
expect(ethLink.getAttribute('href')).toContain(
|
if (!ethLink.parentElement) {
|
||||||
|
throw new Error('ETH link does not exist');
|
||||||
|
}
|
||||||
|
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||||
`/address/${fullMock.sourceEthereumAddress}`
|
`/address/${fullMock.sourceEthereumAddress}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
+9
-3
@@ -62,14 +62,20 @@ describe('Chain Event: ERC20 Asset List', () => {
|
|||||||
expect(screen.getByText(t('Added Vega asset'))).toBeInTheDocument();
|
expect(screen.getByText(t('Added Vega asset'))).toBeInTheDocument();
|
||||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
expect(assetLink).toBeInTheDocument();
|
expect(assetLink).toBeInTheDocument();
|
||||||
expect(assetLink.tagName).toEqual('A');
|
if (!assetLink.parentElement) {
|
||||||
expect(assetLink.getAttribute('href')).toEqual(
|
throw new Error('Asset link does not exist');
|
||||||
|
}
|
||||||
|
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/assets#${fullMock.vegaAssetId}`
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
const ethLink = screen.getByText(`${fullMock.assetSource}`);
|
const ethLink = screen.getByText(`${fullMock.assetSource}`);
|
||||||
expect(ethLink.getAttribute('href')).toContain(
|
if (!ethLink.parentElement) {
|
||||||
|
throw new Error('Asset link does not exist');
|
||||||
|
}
|
||||||
|
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||||
`/address/${fullMock.assetSource}`
|
`/address/${fullMock.assetSource}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
+14
-5
@@ -62,21 +62,30 @@ describe('Chain Event: ERC20 asset deposit', () => {
|
|||||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
const partyLink = screen.getByText(`${fullMock.targetPartyId}`);
|
const partyLink = screen.getByText(`${fullMock.targetPartyId}`);
|
||||||
expect(partyLink).toBeInTheDocument();
|
expect(partyLink).toBeInTheDocument();
|
||||||
expect(partyLink.tagName).toEqual('A');
|
if (!partyLink.parentElement) {
|
||||||
expect(partyLink.getAttribute('href')).toEqual(
|
throw new Error('Party link does not exist');
|
||||||
|
}
|
||||||
|
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/parties/${fullMock.targetPartyId}`
|
`/parties/${fullMock.targetPartyId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
expect(assetLink).toBeInTheDocument();
|
expect(assetLink).toBeInTheDocument();
|
||||||
expect(assetLink.tagName).toEqual('A');
|
if (!assetLink.parentElement) {
|
||||||
expect(assetLink.getAttribute('href')).toEqual(
|
throw new Error('Asset link does not exist');
|
||||||
|
}
|
||||||
|
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/assets#${fullMock.vegaAssetId}`
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
const ethLink = screen.getByText(`${fullMock.sourceEthereumAddress}`);
|
const ethLink = screen.getByText(`${fullMock.sourceEthereumAddress}`);
|
||||||
expect(ethLink.getAttribute('href')).toContain(
|
if (!ethLink.parentElement) {
|
||||||
|
throw new Error('ETH link does not exist');
|
||||||
|
}
|
||||||
|
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||||
`/address/${fullMock.sourceEthereumAddress}`
|
`/address/${fullMock.sourceEthereumAddress}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
+9
-3
@@ -57,14 +57,20 @@ describe('Chain Event: ERC20 asset deposit', () => {
|
|||||||
expect(screen.getByText(t('Asset'))).toBeInTheDocument();
|
expect(screen.getByText(t('Asset'))).toBeInTheDocument();
|
||||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
expect(assetLink).toBeInTheDocument();
|
expect(assetLink).toBeInTheDocument();
|
||||||
expect(assetLink.tagName).toEqual('A');
|
if (!assetLink.parentElement) {
|
||||||
expect(assetLink.getAttribute('href')).toEqual(
|
throw new Error('Asset link does not exist');
|
||||||
|
}
|
||||||
|
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/assets#${fullMock.vegaAssetId}`
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
const ethLink = screen.getByText(`${fullMock.targetEthereumAddress}`);
|
const ethLink = screen.getByText(`${fullMock.targetEthereumAddress}`);
|
||||||
expect(ethLink.getAttribute('href')).toContain(
|
if (!ethLink.parentElement) {
|
||||||
|
throw new Error('ETH link does not exist');
|
||||||
|
}
|
||||||
|
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||||
`/address/${fullMock.targetEthereumAddress}`
|
`/address/${fullMock.targetEthereumAddress}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -64,14 +64,20 @@ describe('Chain Event: Stake deposit', () => {
|
|||||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
const partyLink = screen.getByText(`${fullMock.vegaPublicKey}`);
|
const partyLink = screen.getByText(`${fullMock.vegaPublicKey}`);
|
||||||
expect(partyLink).toBeInTheDocument();
|
expect(partyLink).toBeInTheDocument();
|
||||||
expect(partyLink.tagName).toEqual('A');
|
if (!partyLink.parentElement) {
|
||||||
expect(partyLink.getAttribute('href')).toEqual(
|
throw new Error('Party link does not exist');
|
||||||
|
}
|
||||||
|
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/parties/${fullMock.vegaPublicKey}`
|
`/parties/${fullMock.vegaPublicKey}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
const ethLink = screen.getByText(`${fullMock.ethereumAddress}`);
|
const ethLink = screen.getByText(`${fullMock.ethereumAddress}`);
|
||||||
expect(ethLink.getAttribute('href')).toContain(
|
if (!ethLink.parentElement) {
|
||||||
|
throw new Error('ETH link does not exist');
|
||||||
|
}
|
||||||
|
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||||
`/address/${fullMock.ethereumAddress}`
|
`/address/${fullMock.ethereumAddress}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -64,14 +64,20 @@ describe('Chain Event: Stake remove', () => {
|
|||||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
const partyLink = screen.getByText(`${fullMock.vegaPublicKey}`);
|
const partyLink = screen.getByText(`${fullMock.vegaPublicKey}`);
|
||||||
expect(partyLink).toBeInTheDocument();
|
expect(partyLink).toBeInTheDocument();
|
||||||
expect(partyLink.tagName).toEqual('A');
|
if (!partyLink.parentElement) {
|
||||||
expect(partyLink.getAttribute('href')).toEqual(
|
throw new Error('Party link does not exist');
|
||||||
|
}
|
||||||
|
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||||
|
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||||
`/parties/${fullMock.vegaPublicKey}`
|
`/parties/${fullMock.vegaPublicKey}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
const ethLink = screen.getByText(`${fullMock.ethereumAddress}`);
|
const ethLink = screen.getByText(`${fullMock.ethereumAddress}`);
|
||||||
expect(ethLink.getAttribute('href')).toContain(
|
if (!ethLink.parentElement) {
|
||||||
|
throw new Error('ETH link does not exist');
|
||||||
|
}
|
||||||
|
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||||
`/address/${fullMock.ethereumAddress}`
|
`/address/${fullMock.ethereumAddress}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
+4
-1
@@ -66,7 +66,10 @@ describe('Chain Event: Stake total supply change', () => {
|
|||||||
|
|
||||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
const ethLink = screen.getByText(`${fullMock.tokenAddress}`);
|
const ethLink = screen.getByText(`${fullMock.tokenAddress}`);
|
||||||
expect(ethLink.getAttribute('href')).toContain(
|
if (!ethLink.parentElement) {
|
||||||
|
throw new Error('ETH link does not exist');
|
||||||
|
}
|
||||||
|
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||||
`/address/${fullMock.tokenAddress}`
|
`/address/${fullMock.tokenAddress}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import type { BlockExplorerTransactionResult } from '../../../../routes/types/bl
|
|||||||
import type { TendermintBlocksResponse } from '../../../../routes/blocks/tendermint-blocks-response';
|
import type { TendermintBlocksResponse } from '../../../../routes/blocks/tendermint-blocks-response';
|
||||||
import { Time } from '../../../time';
|
import { Time } from '../../../time';
|
||||||
import { ChainResponseCode } from '../chain-response-code/chain-reponse.code';
|
import { ChainResponseCode } from '../chain-response-code/chain-reponse.code';
|
||||||
|
import { TxDataView } from '../../tx-data-view';
|
||||||
|
import Hash from '../../../links/hash';
|
||||||
|
|
||||||
interface TxDetailsSharedProps {
|
interface TxDetailsSharedProps {
|
||||||
txData: BlockExplorerTransactionResult | undefined;
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
@@ -46,7 +48,7 @@ export const TxDetailsShared = ({
|
|||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell {...sharedHeaderProps}>{t('Hash')}</TableCell>
|
<TableCell {...sharedHeaderProps}>{t('Hash')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<code>{txData.hash}</code>
|
<Hash text={txData.hash} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
@@ -82,6 +84,12 @@ export const TxDetailsShared = ({
|
|||||||
<ChainResponseCode code={txData.code} error={txData.error} />
|
<ChainResponseCode code={txData.code} error={txData.error} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableCell {...sharedHeaderProps}>{t('Transaction')}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<TxDataView blockData={blockData} txData={txData} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,10 +8,8 @@ import { TxDetailsHeartbeat } from './tx-hearbeat';
|
|||||||
import { TxDetailsGeneric } from './tx-generic';
|
import { TxDetailsGeneric } from './tx-generic';
|
||||||
import { TxDetailsBatch } from './tx-batch';
|
import { TxDetailsBatch } from './tx-batch';
|
||||||
import { TxDetailsChainEvent } from './tx-chain-event';
|
import { TxDetailsChainEvent } from './tx-chain-event';
|
||||||
import { TxContent } from '../../../routes/txs/id/tx-content';
|
|
||||||
import { TxDetailsNodeVote } from './tx-node-vote';
|
import { TxDetailsNodeVote } from './tx-node-vote';
|
||||||
import { TxDetailsOrderCancel } from './tx-order-cancel';
|
import { TxDetailsOrderCancel } from './tx-order-cancel';
|
||||||
import get from 'lodash/get';
|
|
||||||
import { TxDetailsOrderAmend } from './tx-order-amend';
|
import { TxDetailsOrderAmend } from './tx-order-amend';
|
||||||
import { TxDetailsWithdrawSubmission } from './tx-withdraw-submission';
|
import { TxDetailsWithdrawSubmission } from './tx-withdraw-submission';
|
||||||
import { TxDetailsDelegate } from './tx-delegation';
|
import { TxDetailsDelegate } from './tx-delegation';
|
||||||
@@ -46,23 +44,9 @@ export const TxDetailsWrapper = ({
|
|||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const raw = get(blockData, `result.block.data.txs[${txData.index}]`);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={`txd-${txData.hash}`}>
|
<div key={`txd-${txData.hash}`}>
|
||||||
<section>{child({ txData, pubKey, blockData })}</section>
|
<section>{child({ txData, pubKey, blockData })}</section>
|
||||||
|
|
||||||
<details title={t('Decoded transaction')} className="mt-3">
|
|
||||||
<summary className="cursor-pointer">{t('Decoded transaction')}</summary>
|
|
||||||
<TxContent data={txData} />
|
|
||||||
</details>
|
|
||||||
|
|
||||||
{raw ? (
|
|
||||||
<details title={t('Raw transaction')} className="mt-3">
|
|
||||||
<summary className="cursor-pointer">{t('Raw transaction')}</summary>
|
|
||||||
<code className="break-all font-mono text-xs">{raw}</code>
|
|
||||||
</details>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { TxDetailsShared } from './shared/tx-details-shared';
|
|||||||
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
||||||
import { txSignatureToDeterministicId } from '../lib/deterministic-ids';
|
import { txSignatureToDeterministicId } from '../lib/deterministic-ids';
|
||||||
import DeterministicOrderDetails from '../../order-details/deterministic-order-details';
|
import DeterministicOrderDetails from '../../order-details/deterministic-order-details';
|
||||||
|
import Hash from '../../links/hash';
|
||||||
|
|
||||||
interface TxDetailsOrderProps {
|
interface TxDetailsOrderProps {
|
||||||
txData: BlockExplorerTransactionResult | undefined;
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
@@ -47,7 +48,7 @@ export const TxDetailsOrder = ({
|
|||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Order')}</TableCell>
|
<TableCell>{t('Order')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<code>{deterministicId}</code>
|
<Hash text={deterministicId} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import get from 'lodash/get';
|
||||||
|
import { Select } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
|
import type { BlockExplorerTransactionResult } from '../../routes/types/block-explorer-response';
|
||||||
|
import type { TendermintBlocksResponse } from '../../routes/blocks/tendermint-blocks-response';
|
||||||
|
|
||||||
|
export function getClassName(showTxData: ShowTxDataType) {
|
||||||
|
const baseClasses =
|
||||||
|
'font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]';
|
||||||
|
if (showTxData === 'JSON') {
|
||||||
|
return `${baseClasses} whitespace-pre overflow-x-scroll`;
|
||||||
|
} else {
|
||||||
|
return baseClasses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getContents(
|
||||||
|
showTxData: ShowTxDataType,
|
||||||
|
txData: BlockExplorerTransactionResult | null,
|
||||||
|
blockData: TendermintBlocksResponse | null | undefined
|
||||||
|
) {
|
||||||
|
if (showTxData === 'JSON') {
|
||||||
|
if (txData) {
|
||||||
|
return JSON.stringify(txData.command, undefined, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (txData && blockData) {
|
||||||
|
return get(blockData, `result.block.data.txs[${txData.index}]`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShowTxDataType = 'JSON' | 'base64';
|
||||||
|
|
||||||
|
interface TxDataViewProps {
|
||||||
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
|
blockData: TendermintBlocksResponse | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TxDataView = ({ txData, blockData }: TxDataViewProps) => {
|
||||||
|
const [showTxData, setShowTxData] = useState<ShowTxDataType>('JSON');
|
||||||
|
|
||||||
|
if (!txData) {
|
||||||
|
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<details title={t('Show raw transaction')}>
|
||||||
|
<summary className="cursor-pointer">{t('Show raw transaction')}</summary>
|
||||||
|
<div className="py-4">
|
||||||
|
<textarea
|
||||||
|
readOnly={true}
|
||||||
|
className={getClassName(showTxData)}
|
||||||
|
rows={12}
|
||||||
|
cols={120}
|
||||||
|
value={getContents(showTxData, txData, blockData)}
|
||||||
|
/>
|
||||||
|
<div className="w-40">
|
||||||
|
<Select
|
||||||
|
placeholder="View as..."
|
||||||
|
onChange={(v) => setShowTxData(v.target.value as ShowTxDataType)}
|
||||||
|
value={'JSON'}
|
||||||
|
>
|
||||||
|
<option value={'JSON'}>JSON</option>
|
||||||
|
<option value={'base64'}>Base64</option>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -115,7 +115,7 @@ export const TxsInfiniteList = ({
|
|||||||
className="List"
|
className="List"
|
||||||
height={995}
|
height={995}
|
||||||
itemCount={itemCount}
|
itemCount={itemCount}
|
||||||
itemSize={isStacked ? 134 : 72}
|
itemSize={isStacked ? 134 : 50}
|
||||||
onItemsRendered={onItemsRendered}
|
onItemsRendered={onItemsRendered}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
width={'100%'}
|
width={'100%'}
|
||||||
|
|||||||
Reference in New Issue
Block a user