fix(explorer): refactor chain event view error handling (#2233)
* feat(explorer): change chain event tx error handling
This commit is contained in:
parent
af7a5630ac
commit
96843cd2be
@ -0,0 +1,453 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
|
||||||
|
|
||||||
|
import { ChainEvent } from '.';
|
||||||
|
|
||||||
|
const baseMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
block: '1',
|
||||||
|
index: 1,
|
||||||
|
hash: '123',
|
||||||
|
submitter: '123',
|
||||||
|
type: '1',
|
||||||
|
code: 1,
|
||||||
|
cursor: '1',
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.mock('./tx-builtin-deposit', () => ({
|
||||||
|
TxDetailsChainEventBuiltinDeposit: () => (
|
||||||
|
<span>TxDetailsChainEventBuiltinDeposit</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-builtin-withdrawal', () => ({
|
||||||
|
TxDetailsChainEventBuiltinWithdrawal: () => (
|
||||||
|
<span>TxDetailsChainEventBuiltinWithdrawal</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-erc20-deposit', () => ({
|
||||||
|
TxDetailsChainEventDeposit: () => <span>TxDetailsChainEventDeposit</span>,
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-erc20-withdrawal', () => ({
|
||||||
|
TxDetailsChainEventWithdrawal: () => (
|
||||||
|
<span>TxDetailsChainEventWithdrawal</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-erc20-asset-list', () => ({
|
||||||
|
TxDetailsChainEventErc20AssetList: () => (
|
||||||
|
<span>TxDetailsChainEventErc20AssetList</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-erc20-asset-delist', () => ({
|
||||||
|
TxDetailsChainEventErc20AssetDelist: () => (
|
||||||
|
<span>TxDetailsChainEventErc20AssetDelist</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-erc20-asset-limits-updated', () => ({
|
||||||
|
TxDetailsChainEventErc20AssetLimitsUpdated: () => (
|
||||||
|
<span>TxDetailsChainEventErc20LimitsUpdated</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-erc20-bridge-pause', () => ({
|
||||||
|
TxDetailsChainEventErc20BridgePause: () => (
|
||||||
|
<span>TxDetailsChainEventErc20BridgeEvent</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-multisig-signer', () => ({
|
||||||
|
TxDetailsChainMultisigSigner: () => <span>TxDetailsChainMultisigSigner</span>,
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-multisig-threshold', () => ({
|
||||||
|
TxDetailsChainMultisigThreshold: () => (
|
||||||
|
<span>TxDetailsChainMultisigThreshold</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-stake-deposit', () => ({
|
||||||
|
TxDetailsChainEventStakeDeposit: () => (
|
||||||
|
<span>TxDetailsChainStakeDeposit</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-stake-remove', () => ({
|
||||||
|
TxDetailsChainEventStakeRemove: () => <span>TxDetailsChainStakeRemove</span>,
|
||||||
|
}));
|
||||||
|
jest.mock('./tx-stake-totalsupply', () => ({
|
||||||
|
TxDetailsChainEventStakeTotalSupply: () => (
|
||||||
|
<span>TxDetailsChainStakeTotalSupply</span>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('Chain Event: Chain Event selects the right component for the event', () => {
|
||||||
|
it('Returns a Built In Deposit event for a built in deposit', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
builtin: {
|
||||||
|
deposit: {
|
||||||
|
amount: '',
|
||||||
|
partyId: '',
|
||||||
|
vegaAssetId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainEventBuiltinDeposit')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a Built In Deposit event for a built in withdrawal', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
builtin: {
|
||||||
|
withdrawal: {
|
||||||
|
amount: '',
|
||||||
|
partyId: '',
|
||||||
|
vegaAssetId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(
|
||||||
|
screen.getByText('TxDetailsChainEventBuiltinWithdrawal')
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a Built In Deposit event for an ERC20 deposit', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20: {
|
||||||
|
deposit: {
|
||||||
|
amount: '',
|
||||||
|
targetPartyId: '',
|
||||||
|
sourceEthereumAddress: '',
|
||||||
|
vegaAssetId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainEventDeposit')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a Built In Deposit event for an ERC20 withdrawal', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20: {
|
||||||
|
withdrawal: {
|
||||||
|
referenceNonce: '',
|
||||||
|
targetEthereumAddress: '',
|
||||||
|
vegaAssetId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainEventWithdrawal')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a Asset List event view for a list', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20: {
|
||||||
|
assetList: {
|
||||||
|
assetSource: '',
|
||||||
|
vegaAssetId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainEventErc20AssetList')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a Asset Delist event view for a delist', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20: {
|
||||||
|
assetDelist: {
|
||||||
|
vegaAssetId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(
|
||||||
|
screen.getByText('TxDetailsChainEventErc20AssetDelist')
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a Asset Limits Update event view for a update', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20: {
|
||||||
|
assetLimitsUpdated: {
|
||||||
|
lifetimeLimits: '100',
|
||||||
|
withdrawThreshold: '100',
|
||||||
|
vegaAssetId: '',
|
||||||
|
sourceEthereumAddress: '0x000',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(
|
||||||
|
screen.getByText('TxDetailsChainEventErc20LimitsUpdated')
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a Bridge Pause event view when a pause event happens', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20: {
|
||||||
|
bridgeStopped: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(
|
||||||
|
screen.getByText('TxDetailsChainEventErc20BridgeEvent')
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a Bridge Pause event view when a resume event happens', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20: {
|
||||||
|
bridgeResumed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(
|
||||||
|
screen.getByText('TxDetailsChainEventErc20BridgeEvent')
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a multsig signer view when a multisig signer is added', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20Multisig: {
|
||||||
|
signerAdded: {
|
||||||
|
blockTime: '100',
|
||||||
|
newSigner: '0x000',
|
||||||
|
nonce: '123',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainMultisigSigner')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a multsig signer view when a multisig signer is removed', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20Multisig: {
|
||||||
|
signerRemoved: {
|
||||||
|
blockTime: '100',
|
||||||
|
oldSigner: '0x000',
|
||||||
|
nonce: '123',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainMultisigSigner')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a multsig signer view when a multisig threshold change event occurs', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
erc20Multisig: {
|
||||||
|
thresholdSet: {
|
||||||
|
blockTime: '100',
|
||||||
|
newThreshold: 100,
|
||||||
|
nonce: '123',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainMultisigThreshold')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a stake deposit view when a stake arrives', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
stakingEvent: {
|
||||||
|
stakeDeposited: {
|
||||||
|
blockTime: '100',
|
||||||
|
amount: '100',
|
||||||
|
vegaPublicKey: '12345',
|
||||||
|
ethereumAddress: '0x123',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainStakeDeposit')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a stake removed view when a stake goes', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
stakingEvent: {
|
||||||
|
stakeRemoved: {
|
||||||
|
blockTime: '100',
|
||||||
|
amount: '100',
|
||||||
|
vegaPublicKey: '12345',
|
||||||
|
ethereumAddress: '0x123',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainStakeRemove')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a stake total supply view when the supply of the staking asset changes', () => {
|
||||||
|
const commandMock: Partial<BlockExplorerTransactionResult> = {
|
||||||
|
command: {
|
||||||
|
chainEvent: {
|
||||||
|
stakingEvent: {
|
||||||
|
totalSupply: {
|
||||||
|
totalSupply: '12345',
|
||||||
|
tokenAddress: '0x123',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mock = Object.assign(
|
||||||
|
{},
|
||||||
|
baseMock,
|
||||||
|
commandMock
|
||||||
|
) as BlockExplorerTransactionResult;
|
||||||
|
|
||||||
|
const screen = render(<ChainEvent txData={mock} />);
|
||||||
|
expect(screen.getByText('TxDetailsChainStakeTotalSupply')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
@ -1,10 +1,10 @@
|
|||||||
import { TxDetailsChainMultisigThreshold } from './tx-multisig-threshold';
|
|
||||||
import { TxDetailsChainMultisigSigner } from './tx-multisig-signer';
|
|
||||||
import { TxDetailsChainEventBuiltinDeposit } from './tx-builtin-deposit';
|
import { TxDetailsChainEventBuiltinDeposit } from './tx-builtin-deposit';
|
||||||
|
import { TxDetailsChainEventBuiltinWithdrawal } from './tx-builtin-withdrawal';
|
||||||
import { TxDetailsChainEventStakeDeposit } from './tx-stake-deposit';
|
import { TxDetailsChainEventStakeDeposit } from './tx-stake-deposit';
|
||||||
import { TxDetailsChainEventStakeRemove } from './tx-stake-remove';
|
import { TxDetailsChainEventStakeRemove } from './tx-stake-remove';
|
||||||
import { TxDetailsChainEventStakeTotalSupply } from './tx-stake-totalsupply';
|
import { TxDetailsChainEventStakeTotalSupply } from './tx-stake-totalsupply';
|
||||||
import { TxDetailsChainEventBuiltinWithdrawal } from './tx-builtin-withdrawal';
|
import { TxDetailsChainMultisigThreshold } from './tx-multisig-threshold';
|
||||||
|
import { TxDetailsChainMultisigSigner } from './tx-multisig-signer';
|
||||||
import { TxDetailsChainEventErc20AssetList } from './tx-erc20-asset-list';
|
import { TxDetailsChainEventErc20AssetList } from './tx-erc20-asset-list';
|
||||||
import { TxDetailsChainEventErc20AssetLimitsUpdated } from './tx-erc20-asset-limits-updated';
|
import { TxDetailsChainEventErc20AssetLimitsUpdated } from './tx-erc20-asset-limits-updated';
|
||||||
import { TxDetailsChainEventErc20BridgePause } from './tx-erc20-bridge-pause';
|
import { TxDetailsChainEventErc20BridgePause } from './tx-erc20-bridge-pause';
|
||||||
@ -13,6 +13,8 @@ import { TxDetailsChainEventDeposit } from './tx-erc20-deposit';
|
|||||||
import isUndefined from 'lodash/isUndefined';
|
import isUndefined from 'lodash/isUndefined';
|
||||||
|
|
||||||
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
|
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
|
||||||
|
import { TxDetailsChainEventWithdrawal } from './tx-erc20-withdrawal';
|
||||||
|
import { TxDetailsChainEventErc20AssetDelist } from './tx-erc20-asset-delist';
|
||||||
|
|
||||||
interface ChainEventProps {
|
interface ChainEventProps {
|
||||||
txData: BlockExplorerTransactionResult | undefined;
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
@ -32,54 +34,58 @@ interface ChainEventProps {
|
|||||||
* @returns React.JSXElement
|
* @returns React.JSXElement
|
||||||
*/
|
*/
|
||||||
export const ChainEvent = ({ txData }: ChainEventProps) => {
|
export const ChainEvent = ({ txData }: ChainEventProps) => {
|
||||||
const e = txData?.command.chainEvent;
|
if (!txData?.command.chainEvent) {
|
||||||
if (!e) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { builtin, erc20, erc20Multisig, stakingEvent } =
|
||||||
|
txData.command.chainEvent;
|
||||||
|
|
||||||
// Builtin Asset events
|
// Builtin Asset events
|
||||||
if (e.builtin) {
|
if (builtin) {
|
||||||
if (e.builtin.deposit) {
|
if (builtin.deposit) {
|
||||||
return <TxDetailsChainEventBuiltinDeposit deposit={e.builtin.deposit} />;
|
return <TxDetailsChainEventBuiltinDeposit deposit={builtin.deposit} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.builtin?.withdrawal) {
|
if (builtin?.withdrawal) {
|
||||||
return (
|
return (
|
||||||
<TxDetailsChainEventBuiltinWithdrawal
|
<TxDetailsChainEventBuiltinWithdrawal
|
||||||
withdrawal={e.builtin?.withdrawal}
|
withdrawal={builtin?.withdrawal}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ERC20 asset events
|
// ERC20 asset events
|
||||||
if (e.erc20) {
|
if (erc20) {
|
||||||
if (e.erc20.deposit) {
|
if (erc20.deposit) {
|
||||||
return <TxDetailsChainEventDeposit deposit={e.erc20.deposit} />;
|
return <TxDetailsChainEventDeposit deposit={erc20.deposit} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.erc20.withdrawal) {
|
if (erc20.withdrawal) {
|
||||||
|
return <TxDetailsChainEventWithdrawal withdrawal={erc20.withdrawal} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (erc20.assetList) {
|
||||||
|
return <TxDetailsChainEventErc20AssetList assetList={erc20.assetList} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (erc20.assetDelist) {
|
||||||
return (
|
return (
|
||||||
<TxDetailsChainEventBuiltinWithdrawal withdrawal={e.erc20.withdrawal} />
|
<TxDetailsChainEventErc20AssetDelist assetDelist={erc20.assetDelist} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.erc20.assetList) {
|
if (erc20.assetLimitsUpdated) {
|
||||||
return (
|
|
||||||
<TxDetailsChainEventErc20AssetList assetList={e.erc20.assetList} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.erc20.assetLimitsUpdated) {
|
|
||||||
return (
|
return (
|
||||||
<TxDetailsChainEventErc20AssetLimitsUpdated
|
<TxDetailsChainEventErc20AssetLimitsUpdated
|
||||||
assetLimitsUpdated={e.erc20.assetLimitsUpdated}
|
assetLimitsUpdated={erc20.assetLimitsUpdated}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bridgeStopped = e.erc20.bridgeStopped;
|
const bridgeStopped = erc20.bridgeStopped;
|
||||||
const bridgeResumed = e.erc20.bridgeResumed;
|
const bridgeResumed = erc20.bridgeResumed;
|
||||||
if (!isUndefined(bridgeStopped) || !isUndefined(bridgeResumed)) {
|
if (!isUndefined(bridgeStopped) || !isUndefined(bridgeResumed)) {
|
||||||
const isPaused = bridgeStopped === false || bridgeResumed === true;
|
const isPaused = bridgeStopped === false || bridgeResumed === true;
|
||||||
return <TxDetailsChainEventErc20BridgePause isPaused={isPaused} />;
|
return <TxDetailsChainEventErc20BridgePause isPaused={isPaused} />;
|
||||||
@ -87,48 +93,48 @@ export const ChainEvent = ({ txData }: ChainEventProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ERC20 multisig events
|
// ERC20 multisig events
|
||||||
if (e.erc20Multisig) {
|
if (erc20Multisig) {
|
||||||
if (e.erc20Multisig.thresholdSet) {
|
if (erc20Multisig.thresholdSet) {
|
||||||
return (
|
return (
|
||||||
<TxDetailsChainMultisigThreshold
|
<TxDetailsChainMultisigThreshold
|
||||||
thresholdSet={e.erc20Multisig.thresholdSet}
|
thresholdSet={erc20Multisig.thresholdSet}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.erc20Multisig.signerAdded) {
|
if (erc20Multisig.signerAdded) {
|
||||||
return (
|
return (
|
||||||
<TxDetailsChainMultisigSigner signer={e.erc20Multisig.signerAdded} />
|
<TxDetailsChainMultisigSigner signer={erc20Multisig.signerAdded} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.erc20Multisig.signerRemoved) {
|
if (erc20Multisig.signerRemoved) {
|
||||||
return (
|
return (
|
||||||
<TxDetailsChainMultisigSigner signer={e.erc20Multisig.signerRemoved} />
|
<TxDetailsChainMultisigSigner signer={erc20Multisig.signerRemoved} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Staking events
|
// Staking events
|
||||||
if (e.stakingEvent) {
|
if (stakingEvent) {
|
||||||
if (e.stakingEvent.stakeDeposited) {
|
if (stakingEvent.stakeDeposited) {
|
||||||
return (
|
return (
|
||||||
<TxDetailsChainEventStakeDeposit
|
<TxDetailsChainEventStakeDeposit
|
||||||
deposit={e.stakingEvent.stakeDeposited}
|
deposit={stakingEvent.stakeDeposited}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.stakingEvent.stakeRemoved) {
|
if (stakingEvent.stakeRemoved) {
|
||||||
return (
|
return (
|
||||||
<TxDetailsChainEventStakeRemove remove={e.stakingEvent.stakeRemoved} />
|
<TxDetailsChainEventStakeRemove remove={stakingEvent.stakeRemoved} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.stakingEvent.totalSupply) {
|
if (stakingEvent.totalSupply) {
|
||||||
return (
|
return (
|
||||||
<TxDetailsChainEventStakeTotalSupply
|
<TxDetailsChainEventStakeTotalSupply
|
||||||
update={e.stakingEvent.totalSupply}
|
update={stakingEvent.totalSupply}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import { getBlockTime } from './get-block-time';
|
||||||
|
|
||||||
|
describe('Lib: getBlockTime', () => {
|
||||||
|
it('- gets returned if nothing is provided', () => {
|
||||||
|
const res = getBlockTime();
|
||||||
|
expect(res).toEqual('-');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns a known date string', () => {
|
||||||
|
const mockBlockTime = '1669223762';
|
||||||
|
const usRes = getBlockTime(mockBlockTime, 'en-US');
|
||||||
|
expect(usRes).toEqual('11/23/2022, 5:16:02 PM');
|
||||||
|
});
|
||||||
|
});
|
@ -4,13 +4,22 @@
|
|||||||
* @param date String or null date
|
* @param date String or null date
|
||||||
* @returns String date in locale time
|
* @returns String date in locale time
|
||||||
*/
|
*/
|
||||||
export function getBlockTime(date?: string) {
|
export function getBlockTime(date?: string, locale?: Intl.LocalesArgument) {
|
||||||
if (!date) {
|
try {
|
||||||
|
if (!date) {
|
||||||
|
throw new Error('No date provided');
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeInSeconds = parseInt(date, 10);
|
||||||
|
|
||||||
|
if (isNaN(timeInSeconds)) {
|
||||||
|
throw new Error('Invalid date');
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeInMs = timeInSeconds * 1000;
|
||||||
|
|
||||||
|
return new Date(timeInMs).toLocaleString(locale);
|
||||||
|
} catch (e) {
|
||||||
return '-';
|
return '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeInSeconds = parseInt(date, 10);
|
|
||||||
const timeInMs = timeInSeconds * 1000;
|
|
||||||
|
|
||||||
return new Date(timeInMs).toLocaleString();
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { TxDetailsChainEventBuiltinDeposit } from './tx-builtin-deposit';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
type Deposit = components['schemas']['vegaBuiltinAssetDeposit'];
|
||||||
|
|
||||||
|
const fullMock: Deposit = {
|
||||||
|
partyId: 'party123',
|
||||||
|
vegaAssetId: 'asset123',
|
||||||
|
amount: 'amount123',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: Builtin asset deposit', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as Deposit;
|
||||||
|
const screen = render(<TxDetailsChainEventBuiltinDeposit deposit={mock} />);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: Deposit = {};
|
||||||
|
|
||||||
|
const screen = render(<TxDetailsChainEventBuiltinDeposit deposit={mock} />);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventBuiltinDeposit deposit={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventBuiltinDeposit deposit={fullMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Built-in asset deposit'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Asset'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.vegaAssetId}`)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Amount'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.amount}`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
|
const partyLink = screen.getByText(`${fullMock.partyId}`);
|
||||||
|
expect(partyLink).toBeInTheDocument();
|
||||||
|
expect(partyLink.tagName).toEqual('A');
|
||||||
|
expect(partyLink.getAttribute('href')).toEqual(
|
||||||
|
`/parties/${fullMock.partyId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
|
expect(assetLink).toBeInTheDocument();
|
||||||
|
expect(assetLink.tagName).toEqual('A');
|
||||||
|
expect(assetLink.getAttribute('href')).toEqual(
|
||||||
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -15,26 +15,26 @@ interface TxDetailsChainEventBuiltinDepositProps {
|
|||||||
export const TxDetailsChainEventBuiltinDeposit = ({
|
export const TxDetailsChainEventBuiltinDeposit = ({
|
||||||
deposit,
|
deposit,
|
||||||
}: TxDetailsChainEventBuiltinDepositProps) => {
|
}: TxDetailsChainEventBuiltinDepositProps) => {
|
||||||
if (!deposit) {
|
if (!deposit || !deposit.partyId || !deposit.vegaAssetId || !deposit.amount) {
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Chain Event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
<TableCell>{t('Built-in asset deposit')}</TableCell>
|
<TableCell>{t('Built-in asset deposit')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Recipient')}</TableCell>
|
<TableCell>{t('Recipient')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<PartyLink id={deposit.partyId || ''} />
|
<PartyLink id={deposit.partyId} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Asset')}</TableCell>
|
<TableCell>{t('Asset')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<AssetLink id={deposit.vegaAssetId || ''} /> ({t('built in asset')})
|
<AssetLink id={deposit.vegaAssetId} /> ({t('built in asset')})
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { TxDetailsChainEventBuiltinWithdrawal } from './tx-builtin-withdrawal';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
type Withdrawal = components['schemas']['vegaBuiltinAssetWithdrawal'];
|
||||||
|
|
||||||
|
const fullMock: Withdrawal = {
|
||||||
|
partyId: 'party123',
|
||||||
|
vegaAssetId: 'asset123',
|
||||||
|
amount: 'amount123',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: Builtin asset withdrawal', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as Withdrawal;
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventBuiltinWithdrawal withdrawal={mock} />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: Withdrawal = {};
|
||||||
|
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventBuiltinWithdrawal withdrawal={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventBuiltinWithdrawal withdrawal={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventBuiltinWithdrawal withdrawal={fullMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText(t('Built-in asset withdrawal'))
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Asset'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.vegaAssetId}`)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Amount'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.amount}`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
|
const partyLink = screen.getByText(`${fullMock.partyId}`);
|
||||||
|
expect(partyLink).toBeInTheDocument();
|
||||||
|
expect(partyLink.tagName).toEqual('A');
|
||||||
|
expect(partyLink.getAttribute('href')).toEqual(
|
||||||
|
`/parties/${fullMock.partyId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
|
expect(assetLink).toBeInTheDocument();
|
||||||
|
expect(assetLink.tagName).toEqual('A');
|
||||||
|
expect(assetLink.getAttribute('href')).toEqual(
|
||||||
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -15,14 +15,19 @@ interface TxDetailsChainEventBuiltinDepositProps {
|
|||||||
export const TxDetailsChainEventBuiltinWithdrawal = ({
|
export const TxDetailsChainEventBuiltinWithdrawal = ({
|
||||||
withdrawal,
|
withdrawal,
|
||||||
}: TxDetailsChainEventBuiltinDepositProps) => {
|
}: TxDetailsChainEventBuiltinDepositProps) => {
|
||||||
if (!withdrawal) {
|
if (
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
!withdrawal ||
|
||||||
|
!withdrawal.partyId ||
|
||||||
|
!withdrawal.vegaAssetId ||
|
||||||
|
!withdrawal.amount
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Chain Event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
<TableCell>{t('Built-in asset withdrawal')}</TableCell>
|
<TableCell>{t('Built-in asset withdrawal')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainEventErc20AssetDelist } from './tx-erc20-asset-delist';
|
||||||
|
|
||||||
|
type Delist = components['schemas']['vegaERC20AssetDelist'];
|
||||||
|
|
||||||
|
const fullMock: Delist = {
|
||||||
|
vegaAssetId: 'asset123',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: ERC20 Asset Delist', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as Delist;
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventErc20AssetDelist assetDelist={mock} />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: Delist = {};
|
||||||
|
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventErc20AssetDelist assetDelist={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventErc20AssetDelist assetDelist={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventErc20AssetDelist assetDelist={fullMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('ERC20 asset removed'))).toBeInTheDocument();
|
||||||
|
|
||||||
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
|
expect(assetLink).toBeInTheDocument();
|
||||||
|
expect(assetLink.tagName).toEqual('A');
|
||||||
|
expect(assetLink.getAttribute('href')).toEqual(
|
||||||
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -16,8 +16,8 @@ interface TxDetailsChainEventErc20AssetDelistProps {
|
|||||||
export const TxDetailsChainEventErc20AssetDelist = ({
|
export const TxDetailsChainEventErc20AssetDelist = ({
|
||||||
assetDelist,
|
assetDelist,
|
||||||
}: TxDetailsChainEventErc20AssetDelistProps) => {
|
}: TxDetailsChainEventErc20AssetDelistProps) => {
|
||||||
if (!assetDelist) {
|
if (!assetDelist || !assetDelist.vegaAssetId) {
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainEventErc20AssetLimitsUpdated } from './tx-erc20-asset-limits-updated';
|
||||||
|
|
||||||
|
type AssetLimitsUpdated = components['schemas']['vegaERC20AssetLimitsUpdated'];
|
||||||
|
|
||||||
|
const fullMock: AssetLimitsUpdated = {
|
||||||
|
sourceEthereumAddress: 'eth123',
|
||||||
|
vegaAssetId: 'asset123',
|
||||||
|
lifetimeLimits: '100',
|
||||||
|
withdrawThreshold: '60',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: ERC20 Asset limits updated', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as AssetLimitsUpdated;
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventErc20AssetLimitsUpdated assetLimitsUpdated={mock} />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: AssetLimitsUpdated = {};
|
||||||
|
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventErc20AssetLimitsUpdated assetLimitsUpdated={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventErc20AssetLimitsUpdated assetLimitsUpdated={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventErc20AssetLimitsUpdated
|
||||||
|
assetLimitsUpdated={fullMock}
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText(t('ERC20 asset limits update'))
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Total lifetime limit'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.lifetimeLimits}`)).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText(t('Asset withdrawal threshold'))
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText(`${fullMock.withdrawThreshold}`)
|
||||||
|
).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Vega asset'))).toBeInTheDocument();
|
||||||
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
|
expect(assetLink).toBeInTheDocument();
|
||||||
|
expect(assetLink.tagName).toEqual('A');
|
||||||
|
expect(assetLink.getAttribute('href')).toEqual(
|
||||||
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('ERC20 asset'))).toBeInTheDocument();
|
||||||
|
const ethLink = screen.getByText(`${fullMock.sourceEthereumAddress}`);
|
||||||
|
expect(ethLink.getAttribute('href')).toContain(
|
||||||
|
`/address/${fullMock.sourceEthereumAddress}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -23,33 +23,35 @@ interface TxDetailsChainEventErc20AssetLimitsUpdatedProps {
|
|||||||
export const TxDetailsChainEventErc20AssetLimitsUpdated = ({
|
export const TxDetailsChainEventErc20AssetLimitsUpdated = ({
|
||||||
assetLimitsUpdated,
|
assetLimitsUpdated,
|
||||||
}: TxDetailsChainEventErc20AssetLimitsUpdatedProps) => {
|
}: TxDetailsChainEventErc20AssetLimitsUpdatedProps) => {
|
||||||
if (!assetLimitsUpdated) {
|
if (
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
!assetLimitsUpdated ||
|
||||||
|
!assetLimitsUpdated.sourceEthereumAddress ||
|
||||||
|
!assetLimitsUpdated.vegaAssetId ||
|
||||||
|
!assetLimitsUpdated.lifetimeLimits ||
|
||||||
|
!assetLimitsUpdated.withdrawThreshold
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Chain event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
<TableCell>{t('ERC20 asset limits updated')}</TableCell>
|
<TableCell>{t('ERC20 asset limits update')}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableCell>{t('ERC20 asset')}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<EthExplorerLink
|
||||||
|
id={assetLimitsUpdated.sourceEthereumAddress}
|
||||||
|
type={EthExplorerLinkTypes.address}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
{assetLimitsUpdated.sourceEthereumAddress ? (
|
|
||||||
<TableRow modifier="bordered">
|
|
||||||
<TableCell>{t('ERC20 asset')}</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<EthExplorerLink
|
|
||||||
id={assetLimitsUpdated.sourceEthereumAddress}
|
|
||||||
type={EthExplorerLinkTypes.address}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Vega asset')}</TableCell>
|
<TableCell>{t('Vega asset')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<AssetLink id={assetLimitsUpdated.vegaAssetId || ''} />
|
<AssetLink id={assetLimitsUpdated.vegaAssetId} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainEventErc20AssetList } from './tx-erc20-asset-list';
|
||||||
|
|
||||||
|
type List = components['schemas']['vegaERC20AssetList'];
|
||||||
|
|
||||||
|
const fullMock: List = {
|
||||||
|
vegaAssetId: 'asset123',
|
||||||
|
assetSource: 'eth123',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: ERC20 Asset List', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as List;
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventErc20AssetList assetList={mock} />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: List = {};
|
||||||
|
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventErc20AssetList assetList={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventErc20AssetList assetList={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventErc20AssetList assetList={fullMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('ERC20 asset added'))).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Added Vega asset'))).toBeInTheDocument();
|
||||||
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
|
expect(assetLink).toBeInTheDocument();
|
||||||
|
expect(assetLink.tagName).toEqual('A');
|
||||||
|
expect(assetLink.getAttribute('href')).toEqual(
|
||||||
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
|
const ethLink = screen.getByText(`${fullMock.assetSource}`);
|
||||||
|
expect(ethLink.getAttribute('href')).toContain(
|
||||||
|
`/address/${fullMock.assetSource}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -19,8 +19,8 @@ interface TxDetailsChainEventErc20AssetListProps {
|
|||||||
export const TxDetailsChainEventErc20AssetList = ({
|
export const TxDetailsChainEventErc20AssetList = ({
|
||||||
assetList,
|
assetList,
|
||||||
}: TxDetailsChainEventErc20AssetListProps) => {
|
}: TxDetailsChainEventErc20AssetListProps) => {
|
||||||
if (!assetList) {
|
if (!assetList || !assetList.assetSource || !assetList.vegaAssetId) {
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -29,21 +29,19 @@ export const TxDetailsChainEventErc20AssetList = ({
|
|||||||
<TableCell>{t('Chain event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
<TableCell>{t('ERC20 asset added')}</TableCell>
|
<TableCell>{t('ERC20 asset added')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
{assetList.assetSource ? (
|
<TableRow modifier="bordered">
|
||||||
<TableRow modifier="bordered">
|
<TableCell>{t('Source')}</TableCell>
|
||||||
<TableCell>{t('Source')}</TableCell>
|
<TableCell>
|
||||||
<TableCell>
|
<EthExplorerLink
|
||||||
<EthExplorerLink
|
id={assetList.assetSource}
|
||||||
id={assetList.assetSource}
|
type={EthExplorerLinkTypes.address}
|
||||||
type={EthExplorerLinkTypes.address}
|
/>
|
||||||
/>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
|
||||||
) : null}
|
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Added Vega asset')}</TableCell>
|
<TableCell>{t('Added Vega asset')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<AssetLink id={assetList.vegaAssetId || ''} />
|
<AssetLink id={assetList.vegaAssetId} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</>
|
</>
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import { TxDetailsChainEventErc20BridgePause } from './tx-erc20-bridge-pause';
|
||||||
|
|
||||||
|
describe('Chain Event: ERC20 bridge pause', () => {
|
||||||
|
it('Renders pause if paused', () => {
|
||||||
|
const screen = render(
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventErc20BridgePause isPaused={true} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('ERC20 bridge pause'))).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders unpause if resumed', () => {
|
||||||
|
const screen = render(
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventErc20BridgePause isPaused={false} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('ERC20 bridge unpause'))).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
@ -1,7 +1,7 @@
|
|||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
import { TableRow, TableCell } from '../../../table';
|
import { TableRow, TableCell } from '../../../table';
|
||||||
|
|
||||||
interface TxDetailsChainEventErc20BridgePauseProps {
|
export interface TxDetailsChainEventErc20BridgePauseProps {
|
||||||
isPaused: boolean;
|
isPaused: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ interface TxDetailsChainEventErc20BridgePauseProps {
|
|||||||
export const TxDetailsChainEventErc20BridgePause = ({
|
export const TxDetailsChainEventErc20BridgePause = ({
|
||||||
isPaused,
|
isPaused,
|
||||||
}: TxDetailsChainEventErc20BridgePauseProps) => {
|
}: TxDetailsChainEventErc20BridgePauseProps) => {
|
||||||
const event = isPaused ? 'pause' : 'unpaused';
|
const event = isPaused ? 'pause' : 'unpause';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainEventDeposit } from './tx-erc20-deposit';
|
||||||
|
|
||||||
|
type Deposit = components['schemas']['vegaERC20Deposit'];
|
||||||
|
|
||||||
|
const fullMock: Deposit = {
|
||||||
|
vegaAssetId: 'asset123',
|
||||||
|
amount: 'amount123',
|
||||||
|
sourceEthereumAddress: 'eth123',
|
||||||
|
targetPartyId: 'vega123',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: ERC20 asset deposit', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as Deposit;
|
||||||
|
const screen = render(<TxDetailsChainEventDeposit deposit={mock} />);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: Deposit = {};
|
||||||
|
|
||||||
|
const screen = render(<TxDetailsChainEventDeposit deposit={mock} />);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(<TxDetailsChainEventDeposit deposit={mock} />);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventDeposit deposit={fullMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('ERC20 deposit'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Asset'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.vegaAssetId}`)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Amount'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.amount}`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
|
const partyLink = screen.getByText(`${fullMock.targetPartyId}`);
|
||||||
|
expect(partyLink).toBeInTheDocument();
|
||||||
|
expect(partyLink.tagName).toEqual('A');
|
||||||
|
expect(partyLink.getAttribute('href')).toEqual(
|
||||||
|
`/parties/${fullMock.targetPartyId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
|
expect(assetLink).toBeInTheDocument();
|
||||||
|
expect(assetLink.tagName).toEqual('A');
|
||||||
|
expect(assetLink.getAttribute('href')).toEqual(
|
||||||
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
|
const ethLink = screen.getByText(`${fullMock.sourceEthereumAddress}`);
|
||||||
|
expect(ethLink.getAttribute('href')).toContain(
|
||||||
|
`/address/${fullMock.sourceEthereumAddress}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -17,8 +17,14 @@ interface TxDetailsChainEventProps {
|
|||||||
export const TxDetailsChainEventDeposit = ({
|
export const TxDetailsChainEventDeposit = ({
|
||||||
deposit,
|
deposit,
|
||||||
}: TxDetailsChainEventProps) => {
|
}: TxDetailsChainEventProps) => {
|
||||||
if (!deposit) {
|
if (
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
!deposit ||
|
||||||
|
!deposit.sourceEthereumAddress ||
|
||||||
|
!deposit.targetPartyId ||
|
||||||
|
!deposit.vegaAssetId ||
|
||||||
|
!deposit.amount
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -27,27 +33,25 @@ export const TxDetailsChainEventDeposit = ({
|
|||||||
<TableCell>{t('Chain event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
<TableCell>{t('ERC20 deposit')}</TableCell>
|
<TableCell>{t('ERC20 deposit')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
{deposit.sourceEthereumAddress ? (
|
<TableRow modifier="bordered">
|
||||||
<TableRow modifier="bordered">
|
<TableCell>{t('Source')}</TableCell>
|
||||||
<TableCell>{t('Source')}</TableCell>
|
<TableCell>
|
||||||
<TableCell>
|
<EthExplorerLink
|
||||||
<EthExplorerLink
|
id={deposit.sourceEthereumAddress}
|
||||||
id={deposit.sourceEthereumAddress}
|
type={EthExplorerLinkTypes.address}
|
||||||
type={EthExplorerLinkTypes.address}
|
/>
|
||||||
/>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
|
||||||
) : null}
|
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Recipient')}</TableCell>
|
<TableCell>{t('Recipient')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<PartyLink id={deposit.targetPartyId || ''} />
|
<PartyLink id={deposit.targetPartyId} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Asset')}</TableCell>
|
<TableCell>{t('Asset')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<AssetLink id={deposit.vegaAssetId || ''} />
|
<AssetLink id={deposit.vegaAssetId} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainEventWithdrawal } from './tx-erc20-withdrawal';
|
||||||
|
type Withdrawal = components['schemas']['vegaERC20Withdrawal'];
|
||||||
|
|
||||||
|
const fullMock: Partial<Withdrawal> = {
|
||||||
|
vegaAssetId: 'asset123',
|
||||||
|
targetEthereumAddress: 'eth123',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: ERC20 asset deposit', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as Withdrawal;
|
||||||
|
const screen = render(<TxDetailsChainEventWithdrawal withdrawal={mock} />);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: Withdrawal = {};
|
||||||
|
|
||||||
|
const screen = render(<TxDetailsChainEventWithdrawal withdrawal={mock} />);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventWithdrawal withdrawal={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventWithdrawal withdrawal={fullMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('ERC20 withdrawal'))).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Asset'))).toBeInTheDocument();
|
||||||
|
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||||
|
expect(assetLink).toBeInTheDocument();
|
||||||
|
expect(assetLink.tagName).toEqual('A');
|
||||||
|
expect(assetLink.getAttribute('href')).toEqual(
|
||||||
|
`/assets#${fullMock.vegaAssetId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
|
const ethLink = screen.getByText(`${fullMock.targetEthereumAddress}`);
|
||||||
|
expect(ethLink.getAttribute('href')).toContain(
|
||||||
|
`/address/${fullMock.targetEthereumAddress}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -17,8 +17,12 @@ interface TxDetailsChainEventWithdrawalProps {
|
|||||||
export const TxDetailsChainEventWithdrawal = ({
|
export const TxDetailsChainEventWithdrawal = ({
|
||||||
withdrawal,
|
withdrawal,
|
||||||
}: TxDetailsChainEventWithdrawalProps) => {
|
}: TxDetailsChainEventWithdrawalProps) => {
|
||||||
if (!withdrawal) {
|
if (
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
!withdrawal ||
|
||||||
|
!withdrawal.targetEthereumAddress ||
|
||||||
|
!withdrawal.vegaAssetId
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -28,22 +32,20 @@ export const TxDetailsChainEventWithdrawal = ({
|
|||||||
<TableCell>{t('ERC20 withdrawal')}</TableCell>
|
<TableCell>{t('ERC20 withdrawal')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
{withdrawal.targetEthereumAddress ? (
|
<TableRow modifier="bordered">
|
||||||
<TableRow modifier="bordered">
|
<TableCell>{t('Recipient')}</TableCell>
|
||||||
<TableCell>{t('Recipient')}</TableCell>
|
<TableCell>
|
||||||
<TableCell>
|
<EthExplorerLink
|
||||||
<EthExplorerLink
|
id={withdrawal.targetEthereumAddress}
|
||||||
id={withdrawal.targetEthereumAddress}
|
type={EthExplorerLinkTypes.address}
|
||||||
type={EthExplorerLinkTypes.address}
|
/>
|
||||||
/>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Asset')}</TableCell>
|
<TableCell>{t('Asset')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<AssetLink id={withdrawal.vegaAssetId || ''} />
|
<AssetLink id={withdrawal.vegaAssetId} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</>
|
</>
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainMultisigSigner } from './tx-multisig-signer';
|
||||||
|
import { getBlockTime } from './lib/get-block-time';
|
||||||
|
|
||||||
|
type Added = components['schemas']['vegaERC20SignerAdded'];
|
||||||
|
type Removed = components['schemas']['vegaERC20SignerRemoved'];
|
||||||
|
|
||||||
|
const mockBlockTime = '1669631323';
|
||||||
|
|
||||||
|
describe('Chain Event: multisig signer change', () => {
|
||||||
|
it('Copes with a poorly formatted time prop', () => {
|
||||||
|
const addedMock: Added = {
|
||||||
|
newSigner: 'eth123',
|
||||||
|
nonce: 'nonce123',
|
||||||
|
blockTime: 'you shall not parse',
|
||||||
|
};
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainMultisigSigner signer={addedMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Signer change at'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('-')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders addedSigner correctly', () => {
|
||||||
|
const addedMock: Added = {
|
||||||
|
newSigner: 'eth123',
|
||||||
|
nonce: 'nonce123',
|
||||||
|
blockTime: mockBlockTime,
|
||||||
|
};
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainMultisigSigner signer={addedMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText(t('Add ERC20 bridge multisig signer'))
|
||||||
|
).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Add signer'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${addedMock.newSigner}`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
const expectedDate = getBlockTime(mockBlockTime);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Signer change at'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(expectedDate)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const removedMock: Removed = {
|
||||||
|
oldSigner: 'eth123',
|
||||||
|
nonce: 'nonce123',
|
||||||
|
blockTime: mockBlockTime,
|
||||||
|
};
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainMultisigSigner signer={removedMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText(t('Remove ERC20 bridge multisig signer'))
|
||||||
|
).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Remove signer'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${removedMock.oldSigner}`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
const expectedDate = getBlockTime(mockBlockTime);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Signer change at'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(expectedDate)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
@ -15,8 +15,8 @@ interface TxDetailsChainMultisigSignerProps {
|
|||||||
export const TxDetailsChainMultisigSigner = ({
|
export const TxDetailsChainMultisigSigner = ({
|
||||||
signer,
|
signer,
|
||||||
}: TxDetailsChainMultisigSignerProps) => {
|
}: TxDetailsChainMultisigSignerProps) => {
|
||||||
if (!signer) {
|
if (!signer || !signer.blockTime) {
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockTime = getBlockTime(signer.blockTime);
|
const blockTime = getBlockTime(signer.blockTime);
|
||||||
@ -30,10 +30,12 @@ export const TxDetailsChainMultisigSigner = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Chain Event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
{'newSigner' in signer
|
<TableCell>
|
||||||
? t('Add ERC20 bridge multisig signer')
|
{'newSigner' in signer
|
||||||
: t('Remove ERC20 bridge multsig signer')}
|
? t('Add ERC20 bridge multisig signer')
|
||||||
|
: t('Remove ERC20 bridge multisig signer')}
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>
|
<TableCell>
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainMultisigThreshold } from './tx-multisig-threshold';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { getBlockTime } from './lib/get-block-time';
|
||||||
|
|
||||||
|
type Threshold =
|
||||||
|
components['schemas']['vegaERC20MultiSigEvent']['thresholdSet'];
|
||||||
|
|
||||||
|
const mockBlockTime = '1669631323';
|
||||||
|
// Note: nonce is missing from this partial because the component does not render
|
||||||
|
// the nonce currently. It could render the nonce, at which point it can be added
|
||||||
|
// here.
|
||||||
|
const fullMock: Partial<Threshold> = {
|
||||||
|
blockTime: mockBlockTime,
|
||||||
|
newThreshold: 667,
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: multisig threshold change', () => {
|
||||||
|
it('Copes with a poorly formatted time prop', () => {
|
||||||
|
const mockWithBadTime: Threshold = {
|
||||||
|
blockTime: '-',
|
||||||
|
newThreshold: 1000,
|
||||||
|
nonce: 'nonce123',
|
||||||
|
};
|
||||||
|
const screen = render(
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainMultisigThreshold thresholdSet={mockWithBadTime} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Threshold change date'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('-')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainMultisigThreshold thresholdSet={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const mock: Threshold = Object.assign({}, fullMock, {
|
||||||
|
nonce: 'nonce123',
|
||||||
|
});
|
||||||
|
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainMultisigThreshold thresholdSet={mock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText(t('ERC20 multisig threshold set'))
|
||||||
|
).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Threshold'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`66.7%`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
const expectedDate = getBlockTime(mockBlockTime);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Threshold change date'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(expectedDate)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
@ -2,23 +2,7 @@ import { t } from '@vegaprotocol/react-helpers';
|
|||||||
import { TableRow, TableCell } from '../../../table';
|
import { TableRow, TableCell } from '../../../table';
|
||||||
import type { components } from '../../../../../types/explorer';
|
import type { components } from '../../../../../types/explorer';
|
||||||
import isNumber from 'lodash/isNumber';
|
import isNumber from 'lodash/isNumber';
|
||||||
|
import { getBlockTime } from './lib/get-block-time';
|
||||||
/**
|
|
||||||
* Returns a reasonably formatted time from unix timestamp of block height
|
|
||||||
*
|
|
||||||
* @param date String or null date
|
|
||||||
* @returns String date in locale time
|
|
||||||
*/
|
|
||||||
function getBlockTime(date?: string) {
|
|
||||||
if (!date) {
|
|
||||||
return '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeInSeconds = parseInt(date, 10);
|
|
||||||
const timeInMs = timeInSeconds * 1000;
|
|
||||||
|
|
||||||
return new Date(timeInMs).toLocaleString();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TxDetailsChainMultisigThresholdProps {
|
interface TxDetailsChainMultisigThresholdProps {
|
||||||
thresholdSet: components['schemas']['vegaERC20MultiSigEvent']['thresholdSet'];
|
thresholdSet: components['schemas']['vegaERC20MultiSigEvent']['thresholdSet'];
|
||||||
@ -27,12 +11,15 @@ interface TxDetailsChainMultisigThresholdProps {
|
|||||||
/**
|
/**
|
||||||
* Someone updated multsig threshold value on the smart contract.
|
* Someone updated multsig threshold value on the smart contract.
|
||||||
* It's a percentage, with 1000 being 100% and 0 being 0%.
|
* It's a percentage, with 1000 being 100% and 0 being 0%.
|
||||||
|
*
|
||||||
|
* - Nonce is not rendered. It's in the full transaction details thing
|
||||||
|
* in case anyone really wants it, but for now it feels like detail we don't need
|
||||||
*/
|
*/
|
||||||
export const TxDetailsChainMultisigThreshold = ({
|
export const TxDetailsChainMultisigThreshold = ({
|
||||||
thresholdSet,
|
thresholdSet,
|
||||||
}: TxDetailsChainMultisigThresholdProps) => {
|
}: TxDetailsChainMultisigThresholdProps) => {
|
||||||
if (!thresholdSet) {
|
if (!thresholdSet || !thresholdSet.blockTime || !thresholdSet.newThreshold) {
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockTime = getBlockTime(thresholdSet.blockTime);
|
const blockTime = getBlockTime(thresholdSet.blockTime);
|
||||||
@ -43,7 +30,7 @@ export const TxDetailsChainMultisigThreshold = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Chain Event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
<TableCell>{t('ERC20 multisig threshold set')}</TableCell>
|
<TableCell>{t('ERC20 multisig threshold set')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
@ -51,7 +38,7 @@ export const TxDetailsChainMultisigThreshold = ({
|
|||||||
<TableCell>{threshold}%</TableCell>
|
<TableCell>{threshold}%</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Threshold set from')}</TableCell>
|
<TableCell>{t('Threshold change date')}</TableCell>
|
||||||
<TableCell>{blockTime}</TableCell>
|
<TableCell>{blockTime}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</>
|
</>
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainEventStakeDeposit } from './tx-stake-deposit';
|
||||||
|
|
||||||
|
type Deposit = components['schemas']['vegaStakeDeposited'];
|
||||||
|
|
||||||
|
const fullMock: Deposit = {
|
||||||
|
amount: 'amount123',
|
||||||
|
blockTime: 'block123',
|
||||||
|
ethereumAddress: 'eth123',
|
||||||
|
vegaPublicKey: 'vega123',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: Stake deposit', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as Deposit;
|
||||||
|
const screen = render(<TxDetailsChainEventStakeDeposit deposit={mock} />);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: Deposit = {};
|
||||||
|
|
||||||
|
const screen = render(<TxDetailsChainEventStakeDeposit deposit={mock} />);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(<TxDetailsChainEventStakeDeposit deposit={mock} />);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventStakeDeposit deposit={fullMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Stake deposit'))).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Amount'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.amount}`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Deposited at'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.blockTime}`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
|
const partyLink = screen.getByText(`${fullMock.vegaPublicKey}`);
|
||||||
|
expect(partyLink).toBeInTheDocument();
|
||||||
|
expect(partyLink.tagName).toEqual('A');
|
||||||
|
expect(partyLink.getAttribute('href')).toEqual(
|
||||||
|
`/parties/${fullMock.vegaPublicKey}`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
|
const ethLink = screen.getByText(`${fullMock.ethereumAddress}`);
|
||||||
|
expect(ethLink.getAttribute('href')).toContain(
|
||||||
|
`/address/${fullMock.ethereumAddress}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -2,33 +2,48 @@ import { t } from '@vegaprotocol/react-helpers';
|
|||||||
import { TableRow, TableCell } from '../../../table';
|
import { TableRow, TableCell } from '../../../table';
|
||||||
import type { components } from '../../../../../types/explorer';
|
import type { components } from '../../../../../types/explorer';
|
||||||
import { PartyLink } from '../../../links';
|
import { PartyLink } from '../../../links';
|
||||||
|
import {
|
||||||
|
EthExplorerLink,
|
||||||
|
EthExplorerLinkTypes,
|
||||||
|
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||||
|
|
||||||
interface TxDetailsChainEventStakeDepositProps {
|
interface TxDetailsChainEventStakeDepositProps {
|
||||||
deposit: components['schemas']['vegaStakeDeposited'];
|
deposit: components['schemas']['vegaStakeDeposited'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Someone addedd some stake for a particular party
|
* Someone added some stake for a particular party
|
||||||
* This should link to the Governance asset, but doesn't
|
* This should link to the Governance asset, but doesn't
|
||||||
* as that would require checking the Network Paramters
|
* as that would require checking the Network Parameters
|
||||||
* Ethereum address should also be a link to an ETH block explorer
|
* Ethereum address should also be a link to an ETH block explorer
|
||||||
*/
|
*/
|
||||||
export const TxDetailsChainEventStakeDeposit = ({
|
export const TxDetailsChainEventStakeDeposit = ({
|
||||||
deposit,
|
deposit,
|
||||||
}: TxDetailsChainEventStakeDepositProps) => {
|
}: TxDetailsChainEventStakeDepositProps) => {
|
||||||
if (!deposit) {
|
if (
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
!deposit ||
|
||||||
|
!deposit.ethereumAddress ||
|
||||||
|
!deposit.vegaPublicKey ||
|
||||||
|
!deposit.amount ||
|
||||||
|
!deposit.blockTime
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Chain Event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
<TableCell>{t('Stake deposited')}</TableCell>
|
<TableCell>{t('Stake deposit')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Source')}</TableCell>
|
<TableCell>{t('Source')}</TableCell>
|
||||||
<TableCell>{deposit.ethereumAddress || ''}</TableCell>
|
<TableCell>
|
||||||
|
<EthExplorerLink
|
||||||
|
id={deposit.ethereumAddress}
|
||||||
|
type={EthExplorerLinkTypes.address}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Recipient')}</TableCell>
|
<TableCell>{t('Recipient')}</TableCell>
|
||||||
@ -42,7 +57,7 @@ export const TxDetailsChainEventStakeDeposit = ({
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Deposited at')}</TableCell>
|
<TableCell>{t('Deposited at')}</TableCell>
|
||||||
<TableCell>{deposit.amount}</TableCell>
|
<TableCell>{deposit.blockTime}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainEventStakeRemove } from './tx-stake-remove';
|
||||||
|
|
||||||
|
type Remove = components['schemas']['vegaStakeRemoved'];
|
||||||
|
|
||||||
|
const fullMock: Remove = {
|
||||||
|
amount: 'amount123',
|
||||||
|
blockTime: 'block123',
|
||||||
|
ethereumAddress: 'eth123',
|
||||||
|
vegaPublicKey: 'vega123',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: Stake remove', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as Remove;
|
||||||
|
const screen = render(<TxDetailsChainEventStakeRemove remove={mock} />);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: Remove = {};
|
||||||
|
|
||||||
|
const screen = render(<TxDetailsChainEventStakeRemove remove={mock} />);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(<TxDetailsChainEventStakeRemove remove={mock} />);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventStakeRemove remove={fullMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(t('Stake remove'))).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Amount'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.amount}`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Removed at'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(`${fullMock.blockTime}`)).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||||
|
const partyLink = screen.getByText(`${fullMock.vegaPublicKey}`);
|
||||||
|
expect(partyLink).toBeInTheDocument();
|
||||||
|
expect(partyLink.tagName).toEqual('A');
|
||||||
|
expect(partyLink.getAttribute('href')).toEqual(
|
||||||
|
`/parties/${fullMock.vegaPublicKey}`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
|
const ethLink = screen.getByText(`${fullMock.ethereumAddress}`);
|
||||||
|
expect(ethLink.getAttribute('href')).toContain(
|
||||||
|
`/address/${fullMock.ethereumAddress}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -2,6 +2,10 @@ import { t } from '@vegaprotocol/react-helpers';
|
|||||||
import { TableRow, TableCell } from '../../../table';
|
import { TableRow, TableCell } from '../../../table';
|
||||||
import type { components } from '../../../../../types/explorer';
|
import type { components } from '../../../../../types/explorer';
|
||||||
import { PartyLink } from '../../../links';
|
import { PartyLink } from '../../../links';
|
||||||
|
import {
|
||||||
|
EthExplorerLink,
|
||||||
|
EthExplorerLinkTypes,
|
||||||
|
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||||
|
|
||||||
interface TxDetailsChainEventStakeRemoveProps {
|
interface TxDetailsChainEventStakeRemoveProps {
|
||||||
remove: components['schemas']['vegaStakeRemoved'];
|
remove: components['schemas']['vegaStakeRemoved'];
|
||||||
@ -16,24 +20,35 @@ interface TxDetailsChainEventStakeRemoveProps {
|
|||||||
export const TxDetailsChainEventStakeRemove = ({
|
export const TxDetailsChainEventStakeRemove = ({
|
||||||
remove,
|
remove,
|
||||||
}: TxDetailsChainEventStakeRemoveProps) => {
|
}: TxDetailsChainEventStakeRemoveProps) => {
|
||||||
if (!remove) {
|
if (
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
!remove ||
|
||||||
|
!remove.ethereumAddress ||
|
||||||
|
!remove.vegaPublicKey ||
|
||||||
|
!remove.amount ||
|
||||||
|
!remove.blockTime
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Chain Event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
<TableCell>{t('Stake removed')}</TableCell>
|
<TableCell>{t('Stake remove')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Source')}</TableCell>
|
<TableCell>{t('Source')}</TableCell>
|
||||||
<TableCell>{remove.ethereumAddress || ''}</TableCell>
|
<TableCell>
|
||||||
|
<EthExplorerLink
|
||||||
|
id={remove.ethereumAddress}
|
||||||
|
type={EthExplorerLinkTypes.address}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Recipient')}</TableCell>
|
<TableCell>{t('Recipient')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<PartyLink id={remove.vegaPublicKey || ''} />
|
<PartyLink id={remove.vegaPublicKey} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
@ -41,7 +56,7 @@ export const TxDetailsChainEventStakeRemove = ({
|
|||||||
<TableCell>{remove.amount}</TableCell>
|
<TableCell>{remove.amount}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Deposited at')}</TableCell>
|
<TableCell>{t('Removed at')}</TableCell>
|
||||||
<TableCell>{remove.blockTime}</TableCell>
|
<TableCell>{remove.blockTime}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</>
|
</>
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { TxDetailsChainEventStakeTotalSupply } from './tx-stake-totalsupply';
|
||||||
|
|
||||||
|
type TotalSupply = components['schemas']['vegaStakeTotalSupply'];
|
||||||
|
|
||||||
|
const fullMock: TotalSupply = {
|
||||||
|
totalSupply: '123000000000000000000000',
|
||||||
|
tokenAddress: 'eth123',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Chain Event: Stake total supply change', () => {
|
||||||
|
it('Renders nothing if no good data is provided', () => {
|
||||||
|
const mock = undefined as unknown as TotalSupply;
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventStakeTotalSupply update={mock} />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders nothing if correct type with no data is provided', () => {
|
||||||
|
const mock: TotalSupply = {};
|
||||||
|
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventStakeTotalSupply update={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`Renders nothing if correct type with partial data is provided`, () => {
|
||||||
|
for (const key in fullMock) {
|
||||||
|
const mock = omit(fullMock, key);
|
||||||
|
const screen = render(
|
||||||
|
<TxDetailsChainEventStakeTotalSupply update={mock} />
|
||||||
|
);
|
||||||
|
expect(screen.container).toBeEmptyDOMElement();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders TableRows if all data is provided', () => {
|
||||||
|
const screen = render(
|
||||||
|
<MockedProvider>
|
||||||
|
<MemoryRouter>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<TxDetailsChainEventStakeTotalSupply update={fullMock} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Chain event type'))).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText(t('Stake total supply update'))
|
||||||
|
).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Total supply'))).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('123,000')).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||||
|
const ethLink = screen.getByText(`${fullMock.tokenAddress}`);
|
||||||
|
expect(ethLink.getAttribute('href')).toContain(
|
||||||
|
`/address/${fullMock.tokenAddress}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -18,33 +18,32 @@ interface TxDetailsChainEventStakeTotalSupplyProps {
|
|||||||
export const TxDetailsChainEventStakeTotalSupply = ({
|
export const TxDetailsChainEventStakeTotalSupply = ({
|
||||||
update,
|
update,
|
||||||
}: TxDetailsChainEventStakeTotalSupplyProps) => {
|
}: TxDetailsChainEventStakeTotalSupplyProps) => {
|
||||||
if (!update) {
|
if (!update || !update.tokenAddress || !update.totalSupply) {
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let totalSupply = update.totalSupply || '';
|
const totalSupply =
|
||||||
if (totalSupply.length > 0) {
|
update.totalSupply.length > 0
|
||||||
totalSupply = formatNumber(toBigNum(totalSupply, 18));
|
? formatNumber(toBigNum(update.totalSupply, 18))
|
||||||
}
|
: update.totalSupply;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Chain Event type')}</TableCell>
|
<TableCell>{t('Chain event type')}</TableCell>
|
||||||
<TableCell>{t('Stake total supply update')}</TableCell>
|
<TableCell>{t('Stake total supply update')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
{update.tokenAddress ? (
|
<TableRow modifier="bordered">
|
||||||
<TableRow modifier="bordered">
|
<TableCell>{t('Source')}</TableCell>
|
||||||
<TableCell>{t('Source')}</TableCell>
|
<TableCell>
|
||||||
<TableCell>
|
<EthExplorerLink
|
||||||
<EthExplorerLink
|
id={update.tokenAddress}
|
||||||
id={update.tokenAddress}
|
type={EthExplorerLinkTypes.address}
|
||||||
type={EthExplorerLinkTypes.address}
|
/>
|
||||||
/>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
|
||||||
) : null}
|
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Total supply')}</TableCell>
|
<TableCell>{t('Total supply')}</TableCell>
|
||||||
<TableCell>{totalSupply}</TableCell>
|
<TableCell>{totalSupply}</TableCell>
|
||||||
|
@ -75,7 +75,7 @@ export function getLabelForChainEvent(
|
|||||||
return t('Staking event');
|
return t('Staking event');
|
||||||
} else if (chainEvent.erc20Multisig) {
|
} else if (chainEvent.erc20Multisig) {
|
||||||
if (chainEvent.erc20Multisig.signerAdded) {
|
if (chainEvent.erc20Multisig.signerAdded) {
|
||||||
return t('Signer adde');
|
return t('Signer added');
|
||||||
} else if (chainEvent.erc20Multisig.signerRemoved) {
|
} else if (chainEvent.erc20Multisig.signerRemoved) {
|
||||||
return t('Signer remove');
|
return t('Signer remove');
|
||||||
} else if (chainEvent.erc20Multisig.thresholdSet) {
|
} else if (chainEvent.erc20Multisig.thresholdSet) {
|
||||||
|
Loading…
Reference in New Issue
Block a user