feat(explorer): state variable proposal tx (#2837)
This commit is contained in:
parent
a5d53eee77
commit
ce832ad6f4
@ -3,6 +3,7 @@ import React from 'react';
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
interface TableProps {
|
interface TableProps {
|
||||||
|
allowWrap?: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
@ -25,8 +26,15 @@ interface TableCellProps extends ThHTMLAttributes<HTMLTableCellElement> {
|
|||||||
modifier?: 'bordered' | 'background';
|
modifier?: 'bordered' | 'background';
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Table = ({ children, className, ...props }: TableProps) => {
|
export const Table = ({
|
||||||
const classes = classnames(className, 'overflow-x-auto whitespace-nowrap');
|
allowWrap,
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: TableProps) => {
|
||||||
|
const classes = allowWrap
|
||||||
|
? className
|
||||||
|
: classnames(className, 'overflow-x-auto whitespace-nowrap');
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<table className="w-full" {...props}>
|
<table className="w-full" {...props}>
|
||||||
@ -37,11 +45,14 @@ export const Table = ({ children, className, ...props }: TableProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const TableWithTbody = ({
|
export const TableWithTbody = ({
|
||||||
|
allowWrap,
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: TableProps) => {
|
}: TableProps) => {
|
||||||
const classes = classnames(className, 'overflow-x-auto whitespace-nowrap');
|
const classes = allowWrap
|
||||||
|
? className
|
||||||
|
: classnames(className, 'overflow-x-auto whitespace-nowrap');
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<table className="w-full" {...props}>
|
<table className="w-full" {...props}>
|
||||||
|
@ -0,0 +1,108 @@
|
|||||||
|
import { getValues } from './bound-factors';
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
|
||||||
|
type KeyValueBundle = components['schemas']['vegaKeyValueBundle'][];
|
||||||
|
|
||||||
|
describe('getValues', () => {
|
||||||
|
it('handles an empty array by returning a dashed template', () => {
|
||||||
|
const res = getValues([]);
|
||||||
|
expect(res).toHaveProperty('down');
|
||||||
|
expect(res.down).toHaveProperty('tolerance', '-');
|
||||||
|
expect(res.down).toHaveProperty('value', '-');
|
||||||
|
expect(res).toHaveProperty('up');
|
||||||
|
expect(res.up).toHaveProperty('tolerance', '-');
|
||||||
|
expect(res.up).toHaveProperty('value', '-');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles undefined', () => {
|
||||||
|
const res = getValues(undefined as unknown as KeyValueBundle);
|
||||||
|
expect(res).toHaveProperty('down');
|
||||||
|
expect(res.down).toHaveProperty('tolerance', '-');
|
||||||
|
expect(res.down).toHaveProperty('value', '-');
|
||||||
|
expect(res).toHaveProperty('up');
|
||||||
|
expect(res.up).toHaveProperty('tolerance', '-');
|
||||||
|
expect(res.up).toHaveProperty('value', '-');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles a kvb that only has one side (should not happen)', () => {
|
||||||
|
const k: KeyValueBundle = [
|
||||||
|
{
|
||||||
|
key: 'up',
|
||||||
|
tolerance: '0.1',
|
||||||
|
value: { vectorVal: { value: ['0.123'] } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = getValues(k);
|
||||||
|
expect(res).toHaveProperty('down');
|
||||||
|
expect(res.down).toHaveProperty('tolerance', '-');
|
||||||
|
expect(res.down).toHaveProperty('value', '-');
|
||||||
|
expect(res).toHaveProperty('up');
|
||||||
|
expect(res.up).toHaveProperty('tolerance', '0.1');
|
||||||
|
expect(res.up).toHaveProperty('value', '0.123');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles a kvb that has a matrixVal instead of a scalarval by ignoring it', () => {
|
||||||
|
const k: KeyValueBundle = [
|
||||||
|
{
|
||||||
|
key: 'up',
|
||||||
|
tolerance: '0.1',
|
||||||
|
value: { matrixVal: { value: [{ value: ['0.123'] }] } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = getValues(k);
|
||||||
|
expect(res).toHaveProperty('down');
|
||||||
|
expect(res.down).toHaveProperty('tolerance', '-');
|
||||||
|
expect(res.down).toHaveProperty('value', '-');
|
||||||
|
expect(res).toHaveProperty('up');
|
||||||
|
expect(res.up).toHaveProperty('tolerance', '0.1');
|
||||||
|
expect(res.up).toHaveProperty('value', '-');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores unexpected extra values in the kvb', () => {
|
||||||
|
const k: KeyValueBundle = [
|
||||||
|
{
|
||||||
|
key: 'up',
|
||||||
|
tolerance: '0.1',
|
||||||
|
value: { vectorVal: { value: ['0.123', '0.77'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'down',
|
||||||
|
tolerance: '0.001',
|
||||||
|
value: { vectorVal: { value: ['0.321'] } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = getValues(k);
|
||||||
|
expect(res).toHaveProperty('down');
|
||||||
|
expect(res.down).toHaveProperty('tolerance', '0.001');
|
||||||
|
expect(res.down).toHaveProperty('value', '0.321');
|
||||||
|
expect(res).toHaveProperty('up');
|
||||||
|
expect(res.up).toHaveProperty('tolerance', '0.1');
|
||||||
|
expect(res.up).toHaveProperty('value', '0.123');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles a full kvb', () => {
|
||||||
|
const k: KeyValueBundle = [
|
||||||
|
{
|
||||||
|
key: 'up',
|
||||||
|
tolerance: '0.1',
|
||||||
|
value: { vectorVal: { value: ['0.123'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'down',
|
||||||
|
tolerance: '0.001',
|
||||||
|
value: { vectorVal: { value: ['0.321'] } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = getValues(k);
|
||||||
|
expect(res).toHaveProperty('down');
|
||||||
|
expect(res.down).toHaveProperty('tolerance', '0.001');
|
||||||
|
expect(res.down).toHaveProperty('value', '0.321');
|
||||||
|
expect(res).toHaveProperty('up');
|
||||||
|
expect(res.up).toHaveProperty('tolerance', '0.1');
|
||||||
|
expect(res.up).toHaveProperty('value', '0.123');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,87 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import { Table, TableRow, TableHeader, TableCell } from '../../../table';
|
||||||
|
|
||||||
|
interface StateVariableProposalBoundFactorsProps {
|
||||||
|
kvb: readonly components['schemas']['vegaKeyValueBundle'][];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dumb as rocks function completely tied to what the structure of this variable should be
|
||||||
|
* @param kvb The key/value bundle
|
||||||
|
* @returns Object
|
||||||
|
*/
|
||||||
|
export function getValues(kvb: StateVariableProposalBoundFactorsProps['kvb']) {
|
||||||
|
const template = {
|
||||||
|
up: {
|
||||||
|
tolerance: '-',
|
||||||
|
value: '-',
|
||||||
|
},
|
||||||
|
down: {
|
||||||
|
tolerance: '-',
|
||||||
|
value: '-',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (kvb && kvb.length > 0) {
|
||||||
|
kvb.forEach((v) => {
|
||||||
|
if (v.key === 'up') {
|
||||||
|
template.up.tolerance = v.tolerance || '-';
|
||||||
|
template.up.value = v.value?.vectorVal?.value
|
||||||
|
? v.value?.vectorVal.value[0]
|
||||||
|
: '-';
|
||||||
|
} else if (v.key === 'down') {
|
||||||
|
template.down.tolerance = v.tolerance || '-';
|
||||||
|
template.down.value = v.value?.vectorVal?.value
|
||||||
|
? v.value?.vectorVal.value[0]
|
||||||
|
: '-';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State Variable proposals updating Bound Factors. This contains two bundles,
|
||||||
|
* an up vector and a down vector
|
||||||
|
*
|
||||||
|
* This is nearly identical to risk factors.
|
||||||
|
*/
|
||||||
|
export const StateVariableProposalBoundFactors = ({
|
||||||
|
kvb,
|
||||||
|
}: StateVariableProposalBoundFactorsProps) => {
|
||||||
|
const v = getValues(kvb);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table allowWrap={true} className="w-1/3">
|
||||||
|
<thead>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableHeader align="left">{t('Parameter')}</TableHeader>
|
||||||
|
<TableHeader align="center">{t('New value')}</TableHeader>
|
||||||
|
<TableHeader align="right">{t('Tolerance')}</TableHeader>
|
||||||
|
</TableRow>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableCell>{t('Up')}</TableCell>
|
||||||
|
<TableCell align="right" className="font-mono">
|
||||||
|
{v.up.value}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right" className="font-mono">
|
||||||
|
{v.up.tolerance}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableCell>{t('Down')}</TableCell>
|
||||||
|
<TableCell align="right" className="font-mono">
|
||||||
|
{v.down.value}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right" className="font-mono">
|
||||||
|
{v.down.tolerance}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import { StateVariableProposalUnknown } from './unknown';
|
||||||
|
import { StateVariableProposalBoundFactors } from './bound-factors';
|
||||||
|
import { StateVariableProposalRiskFactors } from './risk-factors';
|
||||||
|
|
||||||
|
interface StateVariableProposalWrapperProps {
|
||||||
|
stateVariable: string | undefined;
|
||||||
|
kvb: readonly components['schemas']['vegaKeyValueBundle'][] | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State Variable proposals
|
||||||
|
*/
|
||||||
|
export const StateVariableProposalWrapper = ({
|
||||||
|
stateVariable,
|
||||||
|
kvb,
|
||||||
|
}: StateVariableProposalWrapperProps) => {
|
||||||
|
if (!stateVariable || !kvb || kvb.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stateVariable.indexOf('bound-factors') !== -1) {
|
||||||
|
return <StateVariableProposalBoundFactors kvb={kvb} />;
|
||||||
|
} else if (stateVariable.indexOf('risk-factors') !== -1) {
|
||||||
|
return <StateVariableProposalRiskFactors kvb={kvb} />;
|
||||||
|
} else if (stateVariable.indexOf('probability_of_trading') !== -1) {
|
||||||
|
return <StateVariableProposalRiskFactors kvb={kvb} />;
|
||||||
|
} else {
|
||||||
|
return <StateVariableProposalUnknown kvb={kvb} />;
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,124 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import zip from 'lodash/zip';
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import { Table, TableRow, TableHeader, TableCell } from '../../../table';
|
||||||
|
import { StateVariableProposalUnknown } from './unknown';
|
||||||
|
|
||||||
|
interface StateVariableProposalRiskFactorsProps {
|
||||||
|
kvb: readonly components['schemas']['vegaKeyValueBundle'][];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dumb as rocks function completely tied to what the structure of this variable should be
|
||||||
|
*
|
||||||
|
* @param kvb The key/value bundle
|
||||||
|
* @returns Object
|
||||||
|
*/
|
||||||
|
export function getValues(kvb: StateVariableProposalRiskFactorsProps['kvb']) {
|
||||||
|
try {
|
||||||
|
const template = {
|
||||||
|
bid: {
|
||||||
|
offsetTolerance: '-',
|
||||||
|
probabilityTolerance: '-',
|
||||||
|
offset: [] as Readonly<string[]>,
|
||||||
|
probability: [] as Readonly<string[]>,
|
||||||
|
rows: [] as [string | undefined, string | undefined][],
|
||||||
|
},
|
||||||
|
ask: {
|
||||||
|
offsetTolerance: '-',
|
||||||
|
probabilityTolerance: '-',
|
||||||
|
offset: [] as Readonly<string[]>,
|
||||||
|
probability: [] as Readonly<string[]>,
|
||||||
|
rows: [] as [string | undefined, string | undefined][],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
kvb.forEach((v) => {
|
||||||
|
if (v.key === 'bidOffset') {
|
||||||
|
template.bid.offsetTolerance = v.tolerance || '-';
|
||||||
|
template.bid.offset = v.value?.vectorVal?.value
|
||||||
|
? v.value?.vectorVal?.value
|
||||||
|
: ['0'];
|
||||||
|
} else if (v.key === 'bidProbability') {
|
||||||
|
template.bid.probabilityTolerance = v.tolerance || '-';
|
||||||
|
template.bid.probability = v.value?.vectorVal?.value
|
||||||
|
? v.value?.vectorVal?.value
|
||||||
|
: ['0'];
|
||||||
|
} else if (v.key === 'askOffset') {
|
||||||
|
template.ask.offsetTolerance = v.tolerance || '-';
|
||||||
|
template.ask.offset = v.value?.vectorVal?.value
|
||||||
|
? v.value?.vectorVal?.value
|
||||||
|
: ['0'];
|
||||||
|
} else if (v.key === 'askProbability') {
|
||||||
|
template.ask.probabilityTolerance = v.tolerance || '-';
|
||||||
|
template.ask.probability = v.value?.vectorVal?.value
|
||||||
|
? v.value?.vectorVal?.value
|
||||||
|
: ['0'];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bundles up offset and probability in to a row
|
||||||
|
if (template.bid.offset.length > 0 && template.bid.probability.length > 0) {
|
||||||
|
template.bid.rows = zip(template.bid.offset, template.bid.probability);
|
||||||
|
}
|
||||||
|
if (template.ask.offset.length > 0 && template.ask.probability.length > 0) {
|
||||||
|
template.ask.rows = zip(template.ask.offset, template.ask.probability);
|
||||||
|
}
|
||||||
|
|
||||||
|
return template;
|
||||||
|
} catch (e) {
|
||||||
|
// This will result in the table not being rendered
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State Variable proposals updating Risk Factors. This contains two bundles,
|
||||||
|
* a long vector and a short vector
|
||||||
|
*/
|
||||||
|
export const StateVariableProposalRiskFactors = ({
|
||||||
|
kvb,
|
||||||
|
}: StateVariableProposalRiskFactorsProps) => {
|
||||||
|
const v = getValues(kvb);
|
||||||
|
const all = v ? zip(v.bid.rows, v.ask.rows) : [];
|
||||||
|
|
||||||
|
if (all.length === 0) {
|
||||||
|
// Give up, do a JSON view
|
||||||
|
return <StateVariableProposalUnknown kvb={kvb} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table allowWrap={true} className="text-xs lg:text-base max-w-2xl">
|
||||||
|
<thead>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableHeader align="left">{t('Mid offset')}</TableHeader>
|
||||||
|
<TableHeader align="right">{t('Bid probability')}</TableHeader>
|
||||||
|
<TableHeader align="right" className="pl-2">
|
||||||
|
{t('Ask probability')}
|
||||||
|
</TableHeader>
|
||||||
|
</TableRow>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{all.map((r) => {
|
||||||
|
// Simple remapping of the data to protect against undefineds
|
||||||
|
const row = {
|
||||||
|
o: r[0] ? r[0][0] : r[1] ? r[1][0] : '-',
|
||||||
|
b: r[0] ? r[0][1] : '-',
|
||||||
|
a: r[1] ? r[1][1] : '-',
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<TableRow key={`${row.o}${row.b}${row.a}`}>
|
||||||
|
<TableCell align="left">{row.o}</TableCell>
|
||||||
|
<TableCell align="right" className="font-mono">
|
||||||
|
{row.b}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right" className="pl-2 font-mono">
|
||||||
|
{row.a}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,168 @@
|
|||||||
|
import { getValues, StateVariableProposalRiskFactors } from './risk-factors';
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
type kvb = components['schemas']['vegaKeyValueBundle'][];
|
||||||
|
|
||||||
|
describe('Risk Factors: getValues', () => {
|
||||||
|
it('returns null if null is passed in', () => {
|
||||||
|
const res = getValues(null as unknown as kvb);
|
||||||
|
expect(res).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a blank template if kvb is empty', () => {
|
||||||
|
const res = getValues([]);
|
||||||
|
expect(res).not.toBeNull();
|
||||||
|
expect(res?.bid.offsetTolerance).toEqual('-');
|
||||||
|
expect(res?.bid.probabilityTolerance).toEqual('-');
|
||||||
|
expect(res?.bid.probability).toEqual([]);
|
||||||
|
expect(res?.bid.offset).toEqual([]);
|
||||||
|
expect(res?.bid.rows.length).toEqual(0);
|
||||||
|
|
||||||
|
expect(res?.ask.offsetTolerance).toEqual('-');
|
||||||
|
expect(res?.ask.probabilityTolerance).toEqual('-');
|
||||||
|
expect(res?.ask.probability).toEqual([]);
|
||||||
|
expect(res?.ask.offset).toEqual([]);
|
||||||
|
expect(res?.ask.rows.length).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses out a correct bid offset and probability', () => {
|
||||||
|
const k: kvb = [
|
||||||
|
{
|
||||||
|
key: 'bidOffset',
|
||||||
|
value: { vectorVal: { value: ['1'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'bidProbability',
|
||||||
|
value: { vectorVal: { value: ['2'] } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = getValues(k);
|
||||||
|
expect(res?.bid.offset).toEqual(['1']);
|
||||||
|
expect(res?.bid.probability).toEqual(['2']);
|
||||||
|
expect(res?.bid.rows).toEqual([['1', '2']]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses out a correct ask offset and probability', () => {
|
||||||
|
const k: kvb = [
|
||||||
|
{
|
||||||
|
key: 'askOffset',
|
||||||
|
value: { vectorVal: { value: ['1'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'askProbability',
|
||||||
|
value: { vectorVal: { value: ['2'] } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = getValues(k);
|
||||||
|
expect(res?.ask.offset).toEqual(['1']);
|
||||||
|
expect(res?.ask.probability).toEqual(['2']);
|
||||||
|
expect(res?.ask.rows).toEqual([['1', '2']]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses out a correct ask/bid offset and probability', () => {
|
||||||
|
const k: kvb = [
|
||||||
|
{
|
||||||
|
key: 'askOffset',
|
||||||
|
value: { vectorVal: { value: ['1'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'askProbability',
|
||||||
|
value: { vectorVal: { value: ['2'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'bidOffset',
|
||||||
|
value: { vectorVal: { value: ['3'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'bidProbability',
|
||||||
|
value: { vectorVal: { value: ['4'] } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = getValues(k);
|
||||||
|
expect(res?.ask.rows).toEqual([['1', '2']]);
|
||||||
|
expect(res?.bid.rows).toEqual([['3', '4']]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Risk Factors: component', () => {
|
||||||
|
it('renders 3 rows correctly', () => {
|
||||||
|
const k: kvb = [
|
||||||
|
{
|
||||||
|
key: 'askOffset',
|
||||||
|
value: { vectorVal: { value: ['1.1', '1.2', '1.3'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'askProbability',
|
||||||
|
value: { vectorVal: { value: ['2.2', '2.3', '2.4'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'bidOffset',
|
||||||
|
value: { vectorVal: { value: ['1.1', '1.2', '1.3'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'bidProbability',
|
||||||
|
value: { vectorVal: { value: ['4.4', '4.5', '4.6'] } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const screen = render(<StateVariableProposalRiskFactors kvb={k} />);
|
||||||
|
expect(screen.getByText('Mid offset')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Bid probability')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Ask probability')).toBeInTheDocument();
|
||||||
|
// First row
|
||||||
|
expect(screen.getByText('1.1')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('2.2')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('4.4')).toBeInTheDocument();
|
||||||
|
// Second row
|
||||||
|
expect(screen.getByText('1.2')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('2.3')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('4.5')).toBeInTheDocument();
|
||||||
|
// Third row
|
||||||
|
expect(screen.getByText('1.3')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('2.4')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('4.6')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders uneven row counts correctly', () => {
|
||||||
|
const k: kvb = [
|
||||||
|
{
|
||||||
|
key: 'askOffset',
|
||||||
|
value: { vectorVal: { value: ['1.1'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'askProbability',
|
||||||
|
value: { vectorVal: { value: ['2.2'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'bidOffset',
|
||||||
|
value: { vectorVal: { value: ['1.1', '1.2', '1.3'] } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'bidProbability',
|
||||||
|
value: { vectorVal: { value: ['4.4', '4.5', '4.6'] } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const screen = render(<StateVariableProposalRiskFactors kvb={k} />);
|
||||||
|
expect(screen.getByText('Mid offset')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Bid probability')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Ask probability')).toBeInTheDocument();
|
||||||
|
// First row, as previous test
|
||||||
|
expect(screen.getByText('1.1')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('2.2')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('4.4')).toBeInTheDocument();
|
||||||
|
// Second row - offset comes from bid, not ask
|
||||||
|
expect(screen.getByText('1.2')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('4.5')).toBeInTheDocument();
|
||||||
|
// Third row
|
||||||
|
expect(screen.getByText('1.3')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('4.6')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// The askOffset levels without a probability render -
|
||||||
|
expect(screen.getAllByText('-')).toHaveLength(2);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,52 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
import { Table, TableRow, TableHeader, TableCell } from '../../../table';
|
||||||
|
import { getValues } from './bound-factors';
|
||||||
|
|
||||||
|
interface StateVariableProposalBoundFactorsProps {
|
||||||
|
kvb: readonly components['schemas']['vegaKeyValueBundle'][];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State Variable proposals updating Bound Factors. This contains two bundles,
|
||||||
|
* an up vector and a down vector
|
||||||
|
*
|
||||||
|
* This is nearly identical to risk factors.
|
||||||
|
*/
|
||||||
|
export const StateVariableProposalBoundFactors = ({
|
||||||
|
kvb,
|
||||||
|
}: StateVariableProposalBoundFactorsProps) => {
|
||||||
|
const v = getValues(kvb);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table allowWrap={true} className="w-1/3">
|
||||||
|
<thead>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableHeader align="left">{t('Parameter')}</TableHeader>
|
||||||
|
<TableHeader align="center">{t('New value')}</TableHeader>
|
||||||
|
<TableHeader align="right">{t('Tolerance')}</TableHeader>
|
||||||
|
</TableRow>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableCell>{t('Up')}</TableCell>
|
||||||
|
<TableCell align="right" className="font-mono">
|
||||||
|
{v.up.value}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right" className="font-mono">
|
||||||
|
{v.up.tolerance}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableCell>{t('Down')}</TableCell>
|
||||||
|
<TableCell align="right" className="font-mono">
|
||||||
|
{v.down.value}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right" className="font-mono">
|
||||||
|
{v.down.tolerance}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,16 @@
|
|||||||
|
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import type { components } from '../../../../../types/explorer';
|
||||||
|
|
||||||
|
interface StateVariableProposalUnknownProps {
|
||||||
|
kvb: readonly components['schemas']['vegaKeyValueBundle'][];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State Variable proposals of an unknown type. Let's just dump
|
||||||
|
* it out.
|
||||||
|
*/
|
||||||
|
export const StateVariableProposalUnknown = ({
|
||||||
|
kvb,
|
||||||
|
}: StateVariableProposalUnknownProps) => {
|
||||||
|
return <SyntaxHighlighter data={kvb} />;
|
||||||
|
};
|
@ -53,7 +53,7 @@ export const TxDetailsBatch = ({
|
|||||||
let index = 0;
|
let index = 0;
|
||||||
return (
|
return (
|
||||||
<div key={`tx-${index}`}>
|
<div key={`tx-${index}`}>
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared
|
<TxDetailsShared
|
||||||
txData={txData}
|
txData={txData}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
|
@ -32,7 +32,7 @@ export const TxDetailsChainEvent = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||||
<ChainEvent txData={txData} />
|
<ChainEvent txData={txData} />
|
||||||
</TableWithTbody>
|
</TableWithTbody>
|
||||||
|
@ -38,7 +38,7 @@ export const TxDetailsDataSubmission = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared
|
<TxDetailsShared
|
||||||
txData={txData}
|
txData={txData}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
|
@ -35,7 +35,7 @@ export const TxDetailsDelegate = ({
|
|||||||
txData.command.delegateSubmission;
|
txData.command.delegateSubmission;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||||
{d.nodeId ? (
|
{d.nodeId ? (
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
@ -21,6 +21,7 @@ import { TxDetailsDataSubmission } from './tx-data-submission';
|
|||||||
import { TxProposalVote } from './tx-proposal-vote';
|
import { TxProposalVote } from './tx-proposal-vote';
|
||||||
import { TxDetailsProtocolUpgrade } from './tx-details-protocol-upgrade';
|
import { TxDetailsProtocolUpgrade } from './tx-details-protocol-upgrade';
|
||||||
import { TxDetailsIssueSignatures } from './tx-issue-signatures';
|
import { TxDetailsIssueSignatures } from './tx-issue-signatures';
|
||||||
|
import { TxDetailsStateVariable } from './tx-state-variable-proposal';
|
||||||
|
|
||||||
interface TxDetailsWrapperProps {
|
interface TxDetailsWrapperProps {
|
||||||
txData: BlockExplorerTransactionResult | undefined;
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
@ -102,6 +103,8 @@ function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
|
|||||||
return TxDetailsDelegate;
|
return TxDetailsDelegate;
|
||||||
case 'Undelegate':
|
case 'Undelegate':
|
||||||
return TxDetailsUndelegate;
|
return TxDetailsUndelegate;
|
||||||
|
case 'State Variable Proposal':
|
||||||
|
return TxDetailsStateVariable;
|
||||||
default:
|
default:
|
||||||
return TxDetailsGeneric;
|
return TxDetailsGeneric;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ export const TxDetailsGeneric = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||||
</TableWithTbody>
|
</TableWithTbody>
|
||||||
);
|
);
|
||||||
|
@ -60,7 +60,7 @@ export const TxDetailsHeartbeat = ({
|
|||||||
const blockHeight = txData.command.blockHeight || '';
|
const blockHeight = txData.command.blockHeight || '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Node')}</TableCell>
|
<TableCell>{t('Node')}</TableCell>
|
||||||
|
@ -36,7 +36,7 @@ export const TxDetailsLiquidityAmendment = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared
|
<TxDetailsShared
|
||||||
txData={txData}
|
txData={txData}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
|
@ -37,7 +37,7 @@ export const TxDetailsLiquidityCancellation = ({
|
|||||||
const marketId: string = cancel.marketId || '-';
|
const marketId: string = cancel.marketId || '-';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Market')}</TableCell>
|
<TableCell>{t('Market')}</TableCell>
|
||||||
|
@ -35,7 +35,7 @@ export const TxDetailsLiquiditySubmission = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared
|
<TxDetailsShared
|
||||||
txData={txData}
|
txData={txData}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
|
@ -42,7 +42,7 @@ export const TxDetailsNodeVote = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||||
{data && !!data.deposit
|
{data && !!data.deposit
|
||||||
? TxDetailsNodeVoteDeposit({ deposit: data })
|
? TxDetailsNodeVoteDeposit({ deposit: data })
|
||||||
|
@ -29,7 +29,7 @@ export const TxDetailsOrderAmend = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared
|
<TxDetailsShared
|
||||||
txData={txData}
|
txData={txData}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
|
@ -29,7 +29,7 @@ export const TxDetailsOrderCancel = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared
|
<TxDetailsShared
|
||||||
txData={txData}
|
txData={txData}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
|
@ -39,7 +39,7 @@ export const TxDetailsOrder = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared
|
<TxDetailsShared
|
||||||
txData={txData}
|
txData={txData}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
|
@ -32,7 +32,7 @@ export const TxProposalVote = ({
|
|||||||
|
|
||||||
const vote = txData.command.voteSubmission.value ? '👍' : '👎';
|
const vote = txData.command.voteSubmission.value ? '👍' : '👎';
|
||||||
return (
|
return (
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Proposal ID')}</TableCell>
|
<TableCell>{t('Proposal ID')}</TableCell>
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
import {
|
||||||
|
hackyGetMarketFromStateVariable,
|
||||||
|
hackyGetVariableFromStateVariable,
|
||||||
|
} from './tx-state-variable-proposal';
|
||||||
|
|
||||||
|
describe('Hacky Get market from state variable', () => {
|
||||||
|
it('Extracts a market id from a known state variable proposal id', () => {
|
||||||
|
const knownId =
|
||||||
|
'84fff099818dc4f5319477f0812b4341565cfb32ccf735beede734e386b8108f_5d69ff4a485a9f963272c8614c1d0d84bb8ea57886f5b11aad53f0ccc77731ba_probability_of_trading';
|
||||||
|
const res = hackyGetMarketFromStateVariable(knownId);
|
||||||
|
expect(res).toEqual(
|
||||||
|
'5d69ff4a485a9f963272c8614c1d0d84bb8ea57886f5b11aad53f0ccc77731ba'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns null if the string looks a bit like the known one, but with different segments', () => {
|
||||||
|
const knownId =
|
||||||
|
'5d69ff4a485a9f963272c8614c1d0d84bb8ea57886f5b11aad53f0ccc77731ba_probability_of_trading';
|
||||||
|
const res = hackyGetMarketFromStateVariable(knownId);
|
||||||
|
expect(res).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Handles empty/weird data', () => {
|
||||||
|
expect(hackyGetMarketFromStateVariable(null as unknown as string)).toEqual(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
expect(hackyGetMarketFromStateVariable('')).toEqual(null);
|
||||||
|
expect(
|
||||||
|
hackyGetMarketFromStateVariable(undefined as unknown as string)
|
||||||
|
).toEqual(null);
|
||||||
|
expect(hackyGetMarketFromStateVariable(2 as unknown as string)).toEqual(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Hacky Get Variable from state variable proposal id', () => {
|
||||||
|
it('Extracts an variable name from a known state variable proposal id', () => {
|
||||||
|
const knownId =
|
||||||
|
'84fff099818dc4f5319477f0812b4341565cfb32ccf735beede734e386b8108f_5d69ff4a485a9f963272c8614c1d0d84bb8ea57886f5b11aad53f0ccc77731ba_probability_of_trading';
|
||||||
|
const res = hackyGetVariableFromStateVariable(knownId);
|
||||||
|
expect(res).toEqual('probability of trading');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Handles empty/weird data', () => {
|
||||||
|
expect(
|
||||||
|
hackyGetVariableFromStateVariable(null as unknown as string)
|
||||||
|
).toEqual(null);
|
||||||
|
expect(hackyGetVariableFromStateVariable('')).toEqual(null);
|
||||||
|
expect(
|
||||||
|
hackyGetVariableFromStateVariable(undefined as unknown as string)
|
||||||
|
).toEqual(null);
|
||||||
|
expect(hackyGetVariableFromStateVariable(2 as unknown as string)).toEqual(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,113 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||||
|
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
||||||
|
import { MarketLink } from '../../links';
|
||||||
|
|
||||||
|
import type { components } from '../../../../types/explorer';
|
||||||
|
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||||
|
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||||
|
import { StateVariableProposalWrapper } from './state-variable/data-wrapper';
|
||||||
|
|
||||||
|
interface TxDetailsStateVariableProps {
|
||||||
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
|
pubKey: string | undefined;
|
||||||
|
blockData: TendermintBlocksResponse | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There is no market ID in the event, but it appears to be encoded in to the variable
|
||||||
|
* ID so let's pull it out. MarketLink component will handle if it isn't a real market.
|
||||||
|
*
|
||||||
|
* Given how liable to break this is, it's wrapped in a try catch
|
||||||
|
*
|
||||||
|
* @param stateVarId The full state variable proposal variable name
|
||||||
|
* @returns null or a string market id
|
||||||
|
*/
|
||||||
|
export function hackyGetMarketFromStateVariable(
|
||||||
|
stateVarId?: string
|
||||||
|
): string | null {
|
||||||
|
try {
|
||||||
|
const res = stateVarId ? stateVarId.split('_')[1] : null;
|
||||||
|
return res && res.length === 64 ? res : null;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There is no event name in the event, but it appears to be encoded in to the variable
|
||||||
|
* ID so let's pull it out. Will display nothing if it doesn't parse as expected
|
||||||
|
*
|
||||||
|
* Given how liable to break this is, it's wrapped in a try catch
|
||||||
|
*
|
||||||
|
* @param stateVarId The full state variable proposal variable name
|
||||||
|
* @returns null or a string variable name
|
||||||
|
*/
|
||||||
|
export function hackyGetVariableFromStateVariable(
|
||||||
|
stateVarId?: string
|
||||||
|
): string | null {
|
||||||
|
try {
|
||||||
|
if (!stateVarId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stateVarId.split('_').slice(2).join(' ').replace('-', ' ');
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State Variable proposals
|
||||||
|
*/
|
||||||
|
export const TxDetailsStateVariable = ({
|
||||||
|
txData,
|
||||||
|
pubKey,
|
||||||
|
blockData,
|
||||||
|
}: TxDetailsStateVariableProps) => {
|
||||||
|
if (!txData) {
|
||||||
|
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const command: components['schemas']['v1StateVariableProposal'] =
|
||||||
|
txData.command.stateVariableProposal;
|
||||||
|
|
||||||
|
const variable = hackyGetVariableFromStateVariable(
|
||||||
|
command.proposal?.stateVarId
|
||||||
|
);
|
||||||
|
const marketId = hackyGetMarketFromStateVariable(
|
||||||
|
command.proposal?.stateVarId
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
|
<TxDetailsShared
|
||||||
|
txData={txData}
|
||||||
|
pubKey={pubKey}
|
||||||
|
blockData={blockData}
|
||||||
|
/>
|
||||||
|
{marketId ? (
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableCell>{t('Market')}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<MarketLink id={marketId} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : null}
|
||||||
|
<TableRow modifier="bordered">
|
||||||
|
<TableCell>{t('Variable')}</TableCell>
|
||||||
|
<TableCell className="capitalize">
|
||||||
|
<span>{variable}</span>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableWithTbody>
|
||||||
|
<section>
|
||||||
|
<StateVariableProposalWrapper
|
||||||
|
stateVariable={command.proposal?.stateVarId}
|
||||||
|
kvb={command.proposal?.kvb}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -46,7 +46,7 @@ export const TxDetailsUndelegate = ({
|
|||||||
txData.command.undelegateSubmission;
|
txData.command.undelegateSubmission;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||||
{u.nodeId ? (
|
{u.nodeId ? (
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
@ -41,7 +41,7 @@ export const TxDetailsWithdrawSubmission = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TableWithTbody className="mb-8">
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared
|
<TxDetailsShared
|
||||||
txData={txData}
|
txData={txData}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
|
Loading…
Reference in New Issue
Block a user