Compare commits

..
Author SHA1 Message Date
asiaznik 972c46f8df fixed formatting 2023-03-13 12:02:10 +01:00
Edd 7390246039 fix(explorer): neaten validators mobile view 2023-03-10 16:59:37 +00:00
72 changed files with 5382 additions and 4105 deletions
+4 -4
View File
@@ -1,12 +1,12 @@
# App configuration variables
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/graphql
NX_VEGA_REST=https://api.validators-testnet.vega.xyz/
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://validator-testnet.governance.vega.xyz
NX_TENDERMINT_URL=https://tm-be.validators-testnet.vega.rocks
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.xyz
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.xyz/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
@@ -5,6 +5,7 @@ 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'];
@@ -60,7 +61,10 @@ describe('Chain Event: multisig signer change', () => {
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', () => {
@@ -89,6 +93,9 @@ describe('Chain Event: multisig signer change', () => {
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();
});
});
@@ -6,6 +6,7 @@ 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'];
@@ -73,6 +74,9 @@ describe('Chain Event: multisig threshold change', () => {
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();
});
});
@@ -5,11 +5,6 @@ query ExplorerNewAssetSignatureBundle($id: ID!) {
}
asset(id: $id) {
status
source {
... on ERC20 {
contractAddress
}
}
}
}
@@ -20,10 +15,5 @@ query ExplorerUpdateAssetSignatureBundle($id: ID!) {
}
asset(id: $id) {
status
source {
... on ERC20 {
contractAddress
}
}
}
}
@@ -8,14 +8,14 @@ export type ExplorerNewAssetSignatureBundleQueryVariables = Types.Exact<{
}>;
export type ExplorerNewAssetSignatureBundleQuery = { __typename?: 'Query', erc20ListAssetBundle?: { __typename?: 'Erc20ListAssetBundle', signatures: string, nonce: string } | null, asset?: { __typename?: 'Asset', status: Types.AssetStatus, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } | null };
export type ExplorerNewAssetSignatureBundleQuery = { __typename?: 'Query', erc20ListAssetBundle?: { __typename?: 'Erc20ListAssetBundle', signatures: string, nonce: string } | null, asset?: { __typename?: 'Asset', status: Types.AssetStatus } | null };
export type ExplorerUpdateAssetSignatureBundleQueryVariables = Types.Exact<{
id: Types.Scalars['ID'];
}>;
export type ExplorerUpdateAssetSignatureBundleQuery = { __typename?: 'Query', erc20SetAssetLimitsBundle: { __typename?: 'ERC20SetAssetLimitsBundle', signatures: string, nonce: string }, asset?: { __typename?: 'Asset', status: Types.AssetStatus, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } | null };
export type ExplorerUpdateAssetSignatureBundleQuery = { __typename?: 'Query', erc20SetAssetLimitsBundle: { __typename?: 'ERC20SetAssetLimitsBundle', signatures: string, nonce: string }, asset?: { __typename?: 'Asset', status: Types.AssetStatus } | null };
export const ExplorerNewAssetSignatureBundleDocument = gql`
@@ -26,11 +26,6 @@ export const ExplorerNewAssetSignatureBundleDocument = gql`
}
asset(id: $id) {
status
source {
... on ERC20 {
contractAddress
}
}
}
}
`;
@@ -70,11 +65,6 @@ export const ExplorerUpdateAssetSignatureBundleDocument = gql`
}
asset(id: $id) {
status
source {
... on ERC20 {
contractAddress
}
}
}
}
`;
@@ -110,9 +110,7 @@ export const ProposalStatusIcon = ({ id }: ProposalStatusIconProps) => {
return (
<div className="float-left mr-3">
<Tooltip description={<p>{label}</p>}>
<div>
<Icon name={icon} />
</div>
<Icon name={icon} />
</Tooltip>
</div>
);
@@ -1,12 +1,10 @@
import { Loader } from '@vegaprotocol/ui-toolkit';
import type { ProposalTerms } from '../tx-proposal';
import { BundleError } from './signature-bundle/bundle-error';
import { BundleExists } from './signature-bundle/bundle-exists';
import { useExplorerNewAssetSignatureBundleQuery } from './__generated__/SignatureBundle';
export interface ProposalSignatureBundleByTypeProps {
id: string;
tx?: ProposalTerms['newAsset'] | ProposalTerms['updateAsset'];
}
/**
@@ -18,7 +16,6 @@ export interface ProposalSignatureBundleByTypeProps {
*/
export const ProposalSignatureBundleNewAsset = ({
id,
tx,
}: ProposalSignatureBundleByTypeProps) => {
const { data, error, loading } = useExplorerNewAssetSignatureBundleQuery({
variables: {
@@ -27,20 +24,7 @@ export const ProposalSignatureBundleNewAsset = ({
});
if (loading) {
return (
<div className="w-auto max-w-lg p-5 mt-5">
<Loader />
</div>
);
}
if (
!tx?.changes?.erc20 ||
!tx?.changes?.erc20 ||
!('contractAddress' in tx.changes.erc20) ||
tx.changes.erc20.contractAddress === undefined
) {
return null;
return <Loader />;
}
if (data?.erc20ListAssetBundle?.signatures) {
@@ -48,10 +32,8 @@ export const ProposalSignatureBundleNewAsset = ({
<BundleExists
signatures={data.erc20ListAssetBundle.signatures}
nonce={data.erc20ListAssetBundle.nonce}
assetAddress={tx.changes.erc20.contractAddress}
status={data.asset?.status}
proposalId={id}
tx={tx}
/>
);
} else {
@@ -13,7 +13,6 @@ import { useExplorerUpdateAssetSignatureBundleQuery } from './__generated__/Sign
*/
export const ProposalSignatureBundleUpdateAsset = ({
id,
tx,
}: ProposalSignatureBundleByTypeProps) => {
const { data, error, loading } = useExplorerUpdateAssetSignatureBundleQuery({
variables: {
@@ -25,16 +24,11 @@ export const ProposalSignatureBundleUpdateAsset = ({
return <Loader />;
}
if (data?.asset?.source?.__typename !== 'ERC20') {
return null;
}
if (data?.erc20SetAssetLimitsBundle?.signatures) {
return (
<BundleExists
signatures={data.erc20SetAssetLimitsBundle.signatures}
nonce={data.erc20SetAssetLimitsBundle.nonce}
assetAddress={data.asset.source.contractAddress}
status={data.asset?.status}
proposalId={id}
/>
@@ -0,0 +1,31 @@
import { ProposalSignatureBundleNewAsset } from './signature-bundle-new';
import { ProposalSignatureBundleUpdateAsset } from './signature-bundle-update';
export function format(date: string | undefined, def: string) {
if (!date) {
return def;
}
return new Date().toLocaleDateString() || def;
}
interface ProposalSignatureBundleProps {
id: string;
type: 'NewAsset' | 'UpdateAsset';
}
/**
* Some proposals, if enacted, generate a signature bundle.
* The queries have to be split due to the way the API returns
* errors, hence this slightly redundant feeling switcher.
*/
export const ProposalSignatureBundle = ({
id,
type,
}: ProposalSignatureBundleProps) => {
return type === 'NewAsset' ? (
<ProposalSignatureBundleNewAsset id={id} />
) : (
<ProposalSignatureBundleUpdateAsset id={id} />
);
};
@@ -1,17 +0,0 @@
query ExplorerBundleSigners {
networkParameter(key: "blockchains.ethereumConfig") {
value
}
nodesConnection(pagination: { first: 25 }) {
edges {
node {
id
name
status
ethereumAddress
pubkey
tmPubkey
}
}
}
}
@@ -1,57 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ExplorerBundleSignersQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ExplorerBundleSignersQuery = { __typename?: 'Query', networkParameter?: { __typename?: 'NetworkParameter', value: string } | null, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, name: string, status: Types.NodeStatus, ethereumAddress: string, pubkey: string, tmPubkey: string } } | null> | null } };
export const ExplorerBundleSignersDocument = gql`
query ExplorerBundleSigners {
networkParameter(key: "blockchains.ethereumConfig") {
value
}
nodesConnection(pagination: {first: 25}) {
edges {
node {
id
name
status
ethereumAddress
pubkey
tmPubkey
}
}
}
}
`;
/**
* __useExplorerBundleSignersQuery__
*
* To run a query within a React component, call `useExplorerBundleSignersQuery` and pass it any options that fit your needs.
* When your component renders, `useExplorerBundleSignersQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useExplorerBundleSignersQuery({
* variables: {
* },
* });
*/
export function useExplorerBundleSignersQuery(baseOptions?: Apollo.QueryHookOptions<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>(ExplorerBundleSignersDocument, options);
}
export function useExplorerBundleSignersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>(ExplorerBundleSignersDocument, options);
}
export type ExplorerBundleSignersQueryHookResult = ReturnType<typeof useExplorerBundleSignersQuery>;
export type ExplorerBundleSignersLazyQueryHookResult = ReturnType<typeof useExplorerBundleSignersLazyQuery>;
export type ExplorerBundleSignersQueryResult = Apollo.QueryResult<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>;
@@ -8,33 +8,14 @@ import { BundleError } from './bundle-error';
describe('Bundle Error', () => {
const NON_ENABLED_STATUS: AssetStatus[] = [
AssetStatus.STATUS_PENDING_LISTING,
];
const NOT_SHOWN_STATUS: AssetStatus[] = [
AssetStatus.STATUS_PROPOSED,
AssetStatus.STATUS_REJECTED,
];
const ENABLED_STATUS: AssetStatus[] = [AssetStatus.STATUS_ENABLED];
it.each(NOT_SHOWN_STATUS)(
'does not render for proposed or rejected bundles',
(status) => {
const screen = render(
<MemoryRouter>
<MockedProvider>
<BundleError
error={{ message: 'test-error-message' } as ApolloError}
status={status}
/>
</MockedProvider>
</MemoryRouter>
);
expect(screen.container).toBeEmptyDOMElement();
}
);
it.each(NON_ENABLED_STATUS)(
'shows the apollo error in a syntax highlighter if not enabled and a message is provided',
'shows the apollo error if not enabled and a message is provided',
(status) => {
const screen = render(
<MemoryRouter>
@@ -47,7 +28,7 @@ describe('Bundle Error', () => {
</MemoryRouter>
);
expect(screen.getByText('No signature bundle')).toBeInTheDocument();
expect(screen.getByText('test-error-message')).toBeInTheDocument();
}
);
@@ -62,7 +43,7 @@ describe('Bundle Error', () => {
</MemoryRouter>
);
expect(screen.getByText('No signature bundle')).toBeInTheDocument();
expect(screen.getByText('No bundle for proposal ID')).toBeInTheDocument();
}
);
@@ -2,8 +2,8 @@ import type { ApolloError } from '@apollo/client';
import type { AssetStatus } from '@vegaprotocol/types';
import { t } from '@vegaprotocol/i18n';
import Hash from '../../../../links/hash';
import { IconForBundleStatus } from './bundle-icon';
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
export interface BundleErrorProps {
status?: AssetStatus;
@@ -17,33 +17,18 @@ export interface BundleErrorProps {
* the status - if it's already enabled, pretend this isn't an error
*/
export const BundleError = ({ status, error }: BundleErrorProps) => {
if (!status || status === 'STATUS_PROPOSED' || status === 'STATUS_REJECTED') {
// If there is no status, there is no asset and no bundle - ProposalDetails will make it clear why.
// If the asset exists but is just proposed, or rejected, there won't be a signature bundle yet
return null;
}
return (
<div className="w-auto max-w-lg border-2 border-solid border-vega-light-100 dark:border-vega-dark-200 p-5 mt-5">
<IconForBundleStatus status={status} />
<h1 className="text-xl pb-1">{t('No signature bundle')}</h1>
<h1 className="text-xl pb-1">{t('No signature bundle found')}</h1>
<p className="my-4">
{t(
'No signature bundle was generated as a result of this proposal, or the signature bundle could not be found.'
)}
</p>
<div>
<p>
{status === 'STATUS_ENABLED' ? (
t('Asset already enabled')
) : (
<details>
<summary>{t('Show server error message')}</summary>
<SyntaxHighlighter data={error} size="smaller" />
</details>
<Hash text={error ? error.message : t('No bundle for proposal ID')} />
)}
</div>
</p>
</div>
);
};
@@ -32,7 +32,6 @@ describe('Bundle Exists', () => {
nonce={MOCK_NONCE}
proposalId={MOCK_PROPOSAL_ID}
signatures={MOCK_SIGNATURES}
assetAddress={'0x123413423'}
status={status}
/>
</MockedProvider>
@@ -53,7 +52,6 @@ describe('Bundle Exists', () => {
nonce={MOCK_NONCE}
proposalId={MOCK_PROPOSAL_ID}
signatures={MOCK_SIGNATURES}
assetAddress={'0x123413423'}
status={status}
/>
</MockedProvider>
@@ -1,17 +1,14 @@
import { t } from '@vegaprotocol/i18n';
import type { AssetStatus } from '@vegaprotocol/types';
import ProposalLink from '../../../../links/proposal-link/proposal-link';
import { IconForBundleStatus } from './bundle-icon';
import type { AssetStatus } from '@vegaprotocol/types';
import type { ProposalTerms } from '../../tx-proposal';
import { BundleSigners } from './bundle-signers';
import { ProposalSignatureBundleDetails } from './details';
export interface BundleExistsProps {
signatures: string;
nonce: string;
status?: AssetStatus;
assetAddress: string;
proposalId: string;
tx?: ProposalTerms['newAsset'] | ProposalTerms['updateAsset'];
}
/**
@@ -24,11 +21,7 @@ export const BundleExists = ({
nonce,
status,
proposalId,
assetAddress,
tx,
}: BundleExistsProps) => {
// Note if this is wrong, the wrong decoder will be used which will give incorrect data
return (
<div className="w-auto max-w-lg border-2 border-solid border-vega-light-100 dark:border-vega-dark-200 p-5 mt-5">
<IconForBundleStatus status={status} />
@@ -38,42 +31,7 @@ export const BundleExists = ({
: t('Signature bundle generated')}
</h1>
<details className="mt-5">
<summary>{t('Signature bundle details')}</summary>
<div className="ml-4">
<h2 className="text-lg mt-2 mb-2">{t('Signatures')}</h2>
<p>
<textarea
className="font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]"
readOnly={true}
rows={12}
cols={120}
value={signatures}
/>
</p>
<h2 className="text-lg mt-5 mb-2">{t('Nonce')}</h2>
<p>
<textarea
className="font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]"
readOnly={true}
rows={2}
cols={120}
value={nonce}
/>
</p>
</div>
</details>
<BundleSigners
signatures={signatures}
nonce={nonce}
tx={tx}
id={proposalId}
assetAddress={assetAddress}
/>
<ProposalSignatureBundleDetails signatures={signatures} nonce={nonce} />
{status !== 'STATUS_ENABLED' ? (
<p className="mt-5">
@@ -1,34 +1,33 @@
import { render } from '@testing-library/react';
import { AssetStatus } from '@vegaprotocol/types';
import { getIcon } from './bundle-icon';
import { IconForBundleStatus } from './bundle-icon';
describe('Bundle status icon', () => {
const NON_ENABLED_STATUS: AssetStatus[] = [
AssetStatus.STATUS_PENDING_LISTING,
AssetStatus.STATUS_PROPOSED,
AssetStatus.STATUS_REJECTED,
];
const ERROR_STATUS: AssetStatus[] = [AssetStatus.STATUS_REJECTED];
const ENABLED_STATUS: AssetStatus[] = [AssetStatus.STATUS_ENABLED];
it.each(NON_ENABLED_STATUS)(
'show a sparkle icon if the bundle is unused',
(status) => {
expect(getIcon(status)).toEqual('clean');
}
);
it.each(ERROR_STATUS)(
'show an error icon if the bundle is unavailable',
(status) => {
expect(getIcon(status)).toEqual('disable');
const screen = render(<IconForBundleStatus status={status} />);
const i = screen.getByRole('img');
expect(i).toHaveAttribute('aria-label');
expect(i.getAttribute('aria-label')).toMatch(/clean/);
}
);
it.each(ENABLED_STATUS)(
'shows a tick if the bundle is already used',
(status) => {
expect(getIcon(status)).toEqual('tick-circle');
const screen = render(<IconForBundleStatus status={status} />);
const i = screen.getByRole('img');
expect(i).toHaveAttribute('aria-label');
expect(i.getAttribute('aria-label')).toMatch(/tick-circle/);
}
);
});
@@ -12,26 +12,6 @@ export interface IconForBundleStatusProps {
* asset should not exist
*/
export const IconForBundleStatus = ({ status }: IconForBundleStatusProps) => {
const i = getIcon(status);
return (
<Icon
className="float-left mt-2 mr-3"
name={i}
data-testid={i}
ariaLabel={status}
/>
);
const i: IconName = status === 'STATUS_ENABLED' ? 'tick-circle' : 'clean';
return <Icon className="float-left mt-2 mr-3" name={i} />;
};
export function getIcon(status?: AssetStatus): IconName {
switch (status) {
case 'STATUS_ENABLED':
return 'tick-circle';
case undefined:
case 'STATUS_REJECTED':
return 'disable';
default:
return 'clean';
}
}
@@ -1,94 +0,0 @@
import type { EncodeListAssetParameters } from '../../../../../lib/encoders/abis/list-asset';
import type { BridgeFunction } from './bundle-signers';
import {
getBridgeAddressFromNetworkParameter,
getSigners,
} from './bundle-signers';
describe('Bundle Signers helpers', () => {
it('getBridgeAddressFromNetworkParameter handles invalid json', () => {
expect(getBridgeAddressFromNetworkParameter('hi')).toEqual(null);
expect(getBridgeAddressFromNetworkParameter('{hi]')).toEqual(null);
expect(getBridgeAddressFromNetworkParameter('{"hi"}')).toEqual(null);
expect(
getBridgeAddressFromNetworkParameter(false as unknown as string)
).toEqual(null);
});
it('getBridgeAddressFromNetworkParameter returns null if bridge adderss is not in expected place', () => {
expect(
getBridgeAddressFromNetworkParameter(`{
"NetworkParamter": false
}`)
).toEqual(null);
expect(
getBridgeAddressFromNetworkParameter(`{
"network_id": "11155111",
"chain_id": "11155111",
"confirmations": 3,
"staking_bridge_contract": {
"address": "0xFFb0A0d4806502ceF491aF1141f66669A1Bd0D03",
"deployment_block_height": 2011705
},
"token_vesting_contract": {
"address": "0x680fF88252FA7071CAce7398e77872d54D781d0B",
"deployment_block_height": 2011709
},
"multisig_control_contract": {
"address": "0x6eBc32d66277D94DB8FF2ccF86E36f37F29a52D3",
"deployment_block_height": 2011699
}
}`)
).toEqual(null);
});
it('getBridgeAddressFromNetworkParameter returns address if the collateral_bridge_contract has an address', () => {
expect(
getBridgeAddressFromNetworkParameter(`{
"network_id": "11155111",
"chain_id": "11155111",
"confirmations": 3,
"collateral_bridge_contract": {
"address": "0x7fe27d970bc8Afc3B11Cc8d9737bfB66B1efd799"
},
"staking_bridge_contract": {
"address": "0xFFb0A0d4806502ceF491aF1141f66669A1Bd0D03",
"deployment_block_height": 2011705
},
"token_vesting_contract": {
"address": "0x680fF88252FA7071CAce7398e77872d54D781d0B",
"deployment_block_height": 2011709
},
"multisig_control_contract": {
"address": "0x6eBc32d66277D94DB8FF2ccF86E36f37F29a52D3",
"deployment_block_height": 2011699
}
}`)
).toEqual('0x7fe27d970bc8Afc3B11Cc8d9737bfB66B1efd799');
});
it('getSigners to return [] in the case of bad inputs', () => {
expect(
getSigners('list_asset', '123', '', {
assetERC20: '123',
assetId: '456',
limit: 'bad',
threshold: 'data',
nonce: 'here',
})
).toEqual([]);
expect(
getSigners('nothing' as unknown as BridgeFunction, '123', '', {
nonce: 'here',
} as unknown as EncodeListAssetParameters)
).toEqual([]);
expect(
getSigners('set_asset_limits', '0x123', '0x456', {
nonce: 'here',
} as unknown as EncodeListAssetParameters)
).toEqual([]);
});
});
@@ -1,197 +0,0 @@
import { encodeListAssetBridgeTx } from '../../../../../lib/encoders/abis/list-asset';
import { recoverAddress } from 'ethers/lib/utils';
import { useExplorerBundleSignersQuery } from './__generated__/BundleSigners';
import type { ProposalTerms } from '../../tx-proposal';
import { DApp, TOKEN_VALIDATOR, useLinks } from '@vegaprotocol/environment';
import { ExternalLink, Icon } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { IconNames } from '@blueprintjs/icons';
import { encodeUpdateAssetBridgeTx } from '../../../../../lib/encoders/abis/update-asset';
import { prepend0x } from '@vegaprotocol/smart-contracts';
import type { EncodeListAssetParameters } from '../../../../../lib/encoders/abis/list-asset';
import omit from 'lodash/omit';
export type BridgeFunction = 'list_asset' | 'set_asset_limits';
export interface BundleSignersProps {
signatures: string;
assetAddress: string;
nonce: string;
tx?: ProposalTerms['updateAsset'] | ProposalTerms['newAsset'];
id: string;
}
/**
* A logic-heavy component that takes in a signature bundle and returns
* the list of validators that signed the bundle. To do this it requires
* data from quite a few places - a network parameter, the signature bundle,
* the asset that has been modified
*/
export const BundleSigners = ({
signatures,
nonce,
assetAddress,
tx,
id,
}: BundleSignersProps) => {
const tokenLink = useLinks(DApp.Token);
const bridgeFunction: BridgeFunction =
tx?.changes?.erc20 && 'contractAddress' in tx.changes.erc20
? 'list_asset'
: 'set_asset_limits';
const { data } = useExplorerBundleSignersQuery();
const bridgeAddress = getBridgeAddressFromNetworkParameter(
data?.networkParameter?.value
);
const allEthereumKeys =
data?.nodesConnection?.edges
?.filter((n) => n?.node.status === 'NODE_STATUS_VALIDATOR')
.map((s) => s?.node) || [];
if (!tx || !tx.changes?.erc20) {
return null;
}
const { lifetimeLimit, withdrawThreshold } = tx.changes.erc20;
if (
!id ||
allEthereumKeys.length === 0 ||
!bridgeAddress ||
!lifetimeLimit ||
!withdrawThreshold
) {
return null;
}
const signersLowerCase = getSigners(
bridgeFunction,
bridgeAddress,
signatures,
{
assetERC20: assetAddress,
assetId: prepend0x(id),
limit: lifetimeLimit,
threshold: withdrawThreshold,
nonce,
}
);
return (
<>
<h2 className="mt-4 mb-2 text-lg">{t('Signed by validators')}</h2>
<ul>
{allEthereumKeys?.map((n) => {
if (!n) {
return null;
}
const validatorPage = tokenLink(TOKEN_VALIDATOR.replace(':id', n.id));
return signersLowerCase?.indexOf(
n?.ethereumAddress.toLowerCase() || '??'
) !== -1 ? (
<li key={n?.pubkey}>
<ExternalLink href={validatorPage}>
<Icon name={IconNames.ENDORSED} className="ml-1 mr-2" />
{n?.name}
<Icon size={3} name={IconNames.SHARE} className="ml-2" />
</ExternalLink>
</li>
) : (
<li>
<ExternalLink href={validatorPage}>
<Icon name={IconNames.MINUS} className="ml-1 mr-2" />
{n?.name}
<Icon size={3} name={IconNames.SHARE} className="ml-2" />
</ExternalLink>
</li>
);
})}
</ul>
</>
);
};
/**
* Given all of the collated information, this function creates an equivalent unsigned bundle
* and recovers the signers from it, In the case of an error, it returns an empty array.
*
* @param bridgeFunction Decides which data goes in to the digest
* @param bridgeAddress ERC20 bridge address
* @param signatures Long string of signatures
* @param params The object containing all data that the bridge requires for New or Updating assets
* @returns String[] Empty if there was an error or no signers were recovered, otherwise lowercased ETH addresses
*/
export function getSigners(
bridgeFunction: BridgeFunction,
bridgeAddress: string,
signatures: string,
params: EncodeListAssetParameters
): string[] {
try {
if (bridgeFunction === 'list_asset') {
const digest = encodeListAssetBridgeTx(params, bridgeAddress);
// Recover Address from digest can return null, which is handled as an empty array
return recoverAddressesFromDigest(digest, signatures) || [];
} else {
// The params bundles are so similar, rather than force the component to make two different
// styles, just delete the one different property
const p = omit(params, 'assetId');
const digest = encodeUpdateAssetBridgeTx(p, bridgeAddress);
return recoverAddressesFromDigest(digest, signatures) || [];
}
} catch (e) {
// In the worst case, no signing addresses are recovered. This means that all nodes will
// be rendered as if they had not signed the bundle.
return [];
}
}
/**
* Querying for the network parameter value gets us all of the contract details for this network
* encoded as a JSON object. This function pulls out the address for the bridge, or returns null
* in any of the many cases where it may fail
*
* @param networkParameterAsString the stringified JSON object
* @returns null or bridge address as a string
*/
export function getBridgeAddressFromNetworkParameter(
networkParameterAsString: string | undefined
): string | null {
if (!networkParameterAsString) {
return null;
}
try {
const networkParameter = JSON.parse(networkParameterAsString);
return networkParameter.collateral_bridge_contract.address;
} catch (e) {
// There is no good recovery state so return null
return null;
}
}
export function recoverAddressesFromDigest(
digest: string,
unprefixedBundle: string
) {
// Remove 0x from bundle, then split it in to signatures
const sigs = unprefixedBundle.substring(2).match(/.{1,130}/g);
// Convert each of the signatures from hex to a string
const hexSigs = sigs?.map((s) => `0x${s.toString()}`);
if (!hexSigs) {
return null;
}
// toLowerCase is a hack - something somewhere is lowercasing some
// pubkeys
return hexSigs.map((h) => recoverAddress(digest, h).toLowerCase());
}
@@ -0,0 +1,41 @@
import { t } from '@vegaprotocol/i18n';
export interface ProposalSignatureBundleDetailsProps {
signatures: string;
nonce: string;
}
export const ProposalSignatureBundleDetails = ({
signatures,
nonce,
}: ProposalSignatureBundleDetailsProps) => {
return (
<details className="mt-5">
<summary>{t('Signature bundle details')}</summary>
<div className="ml-4">
<h2 className="text-lg mt-2 mb-2">{t('Signatures')}</h2>
<p>
<textarea
className="font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]"
readOnly={true}
rows={12}
cols={120}
value={signatures}
/>
</p>
<h2 className="text-lg mt-5 mb-2">{t('Nonce')}</h2>
<p>
<textarea
className="font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]"
readOnly={true}
rows={2}
cols={120}
value={nonce}
/>
</p>
</div>
</details>
);
};
@@ -61,7 +61,7 @@ export const ProposalSummary = ({
{id && <ProposalStatusIcon id={id} />}
{rationale?.title && <h1 className="text-xl pb-1">{rationale.title}</h1>}
{rationale?.description && (
<div className="pt-2 text-sm leading-tight">
<p className="pt-2 text-sm leading-tight">
<ReactMarkdown
className="react-markdown-container"
skipHtml={true}
@@ -70,15 +70,15 @@ export const ProposalSummary = ({
>
{md}
</ReactMarkdown>
</div>
</p>
)}
<div className="pt-5">
<p className="pt-5">
<button className="underline max-md:hidden mr-5" onClick={openDialog}>
{t('View terms')}
</button>{' '}
<ProposalLink id={id} text={t('Full details')} />
{terms && <ProposalDate terms={terms} id={id} />}
</div>
</p>
<JsonViewerDialog
open={dialog.open}
onChange={(isOpen) => setDialog({ ...dialog, open: isOpen })}
@@ -7,9 +7,8 @@ import { txSignatureToDeterministicId } from '../lib/deterministic-ids';
import has from 'lodash/has';
import { ProposalSummary } from './proposal/summary';
import Hash from '../../links/hash';
import { ProposalSignatureBundle } from './proposal/signature-bundle';
import { t } from '@vegaprotocol/i18n';
import { ProposalSignatureBundleNewAsset } from './proposal/signature-bundle-new';
import { ProposalSignatureBundleUpdateAsset } from './proposal/signature-bundle-update';
export type Proposal = components['schemas']['v1ProposalSubmission'];
export type ProposalTerms = components['schemas']['vegaProposalTerms'];
@@ -79,12 +78,6 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
deterministicId = txSignatureToDeterministicId(sig);
}
const tx = proposal.terms?.newAsset || proposal.terms?.updateAsset;
const SignatureBundleComponent = proposal.terms?.newAsset
? ProposalSignatureBundleNewAsset
: ProposalSignatureBundleUpdateAsset;
return (
<>
<TableWithTbody className="mb-8" allowWrap={true}>
@@ -112,7 +105,10 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
terms={proposal?.terms}
/>
{proposalRequiresSignatureBundle(proposal) && (
<SignatureBundleComponent id={deterministicId} tx={tx} />
<ProposalSignatureBundle
id={deterministicId}
type={proposal.terms?.newAsset ? 'NewAsset' : 'UpdateAsset'}
/>
)}
</>
);
@@ -1,2 +0,0 @@
// The subset of ABI types that we use in relevant types
export type AbiType = 'address' | 'bytes' | 'bytes32' | 'uint256' | 'string';
@@ -1,31 +0,0 @@
import { keccak256, defaultAbiCoder, isAddress } from 'ethers/lib/utils';
import type { AbiType } from './abi-types';
export const BRIDGE_COMMAND: AbiType[] = [
// The abi encoded bytes of the message
'bytes',
// The address of the bridge
'address',
];
/**
* ABI encode values for a bridge call, getting back its digest
*
* @param bytes The packed bytes of the command for the bridge
* @param address the Ethereum address of the ERC20 bridge
* @param raw defaults to false. If set, does not keccak256 the output
*/
export function encodeBridgeCommand(
bytes: string,
address: string,
raw = false
) {
if (!isAddress(address)) {
throw new Error('Bridge address must be a hex value');
}
const values = [bytes, address];
const value = defaultAbiCoder.encode(BRIDGE_COMMAND, values);
return raw === true ? value : keccak256(value);
}
@@ -1,31 +0,0 @@
import { encodeBridgeCommand } from './bridge-command';
describe('Bridge command encoder', () => {
const VALID_BYTES =
'0x000000000000000000000000b063f5504610ba4b8db230d9f884bfadc1e31da00b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b3790000000000000000000000000000000000000000000000487a9a30453944000000000000000000000000000000000000000000000000000000000000000000010b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b37900000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000a6c6973745f617373657400000000000000000000000000000000000000000000';
const VALID_ADDRESS = '0x7fe27d970bc8Afc3B11Cc8d9737bfB66B1efd799';
it('rejects non valid bridge addresses', () => {
expect(() => {
encodeBridgeCommand(VALID_BYTES, '456789');
}).toThrowError('Bridge address must be a hex value');
});
it('throws if the bytes are not bytes-like', () => {
expect(() => {
encodeBridgeCommand('hello', VALID_ADDRESS);
}).toThrowError(/invalid/);
});
it('keccac256s the value by default', () => {
const res = encodeBridgeCommand(VALID_BYTES, VALID_ADDRESS);
// Magic number: Known output, including 0x
expect(res.length).toEqual(66);
});
it('Does not keccac256 the value if third param is set', () => {
const res = encodeBridgeCommand(VALID_BYTES, VALID_ADDRESS, true);
// Magic number: Known output
expect(res.length).toEqual(706);
});
});
@@ -1,76 +0,0 @@
import { encodeListAsset, encodeListAssetBridgeTx } from './list-asset';
describe('List Asset ABI encoder', () => {
it('throws if asset erc20 address is invalid', () => {
expect(() => {
encodeListAsset({
assetERC20: '123',
assetId: '0x456',
limit: '1',
threshold: '1',
nonce: '1',
});
}).toThrowError('Asset ERC20 and assetID must be hex values');
});
it('throws if assetId is not hex encoded', () => {
expect(() => {
encodeListAsset({
assetERC20: '0x123',
assetId: '456',
limit: '1',
threshold: '1',
nonce: '1',
});
}).toThrowError('Asset ERC20 and assetID must be hex values');
});
it('throws if values to not match expected format', () => {
expect(() => {
encodeListAsset({
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
assetId: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
limit: 'not a valid number',
threshold: '1',
nonce: '1',
});
}).toThrowError(/incorrect data length/);
});
it('returns an ABI encoded value if inputs are valid', () => {
const EXPECTED_OUTPUT =
'0x000000000000000000000000b063f5504610ba4b8db230d9f884bfadc1e31da00b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b37900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000a6c6973745f617373657400000000000000000000000000000000000000000000';
const res = encodeListAsset({
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
assetId:
'0x0b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b379',
limit: '1',
threshold: '1',
nonce: '1',
});
expect(res).toEqual(EXPECTED_OUTPUT);
});
it('encodeListAssetBridge returns a keccak256 hash of the bridge tx', () => {
const EXPECTED_OUTPUT =
'0xe0e62b27fe4490025d312bb2e37486f56935a3d9442dc34c2b918b2a28a386f2';
const res = encodeListAssetBridgeTx(
{
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
assetId:
'0x0b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b379',
limit: '1',
threshold: '1',
nonce: '1',
},
'0xb063f5504610ba4b8db230d9f884bfadc1e31da0'
);
// Magic number: keccak256 hash length + '0x'
expect(res.length).toEqual(66);
expect(res).toEqual(EXPECTED_OUTPUT);
});
});
@@ -1,76 +0,0 @@
import { defaultAbiCoder, isAddress, isHexString } from 'ethers/lib/utils';
import { encodeBridgeCommand } from './bridge-command';
import type { AbiType } from './abi-types';
export const METHOD_NAME = 'list_asset';
export const LIST_ASSET_ABI: AbiType[] = [
// Asset address
'address',
// Asset ID on Vega
'bytes32',
// Lifetime limit
'uint256',
// Withdraw threshold
'uint256',
// Nonce
'uint256',
// Contract method name
'string',
];
export interface EncodeListAssetParameters {
// The ETH address of the ERC20 asset
assetERC20: string;
// The Vega ID of the asset, 0x prefixed
assetId: string;
// The number as a string of the asset
limit: string;
// THe number-as-a-string of the withdraw threshold
threshold: string;
// The n-once supplied to the contract
nonce: string;
}
/**
* Generates an ABI encoded function call to list an asset. This is
* used in the Signature Bundle view on some proposals to recover
* which validators signed a multisig bundle. It does this by recovering
* the ERC20 addresses of the signers, then comparing those to the list
* of signers on the bundle. In order to do this, we recreate the signed
* data from the values we know from the transaction. That last part
* is what this function does.
*
* @param EncodeListAssetParameters The arguments for the ABI call
* @returns string encoded message
*/
export function encodeListAsset({
assetERC20,
assetId,
limit,
threshold,
nonce,
}: EncodeListAssetParameters) {
if (!isAddress(assetERC20) || !isHexString(assetId)) {
throw new Error('Asset ERC20 and assetID must be hex values');
}
const values = [assetERC20, assetId, limit, threshold, nonce, METHOD_NAME];
return defaultAbiCoder.encode(LIST_ASSET_ABI, values);
}
/**
* Convenience function that encodes and packs the message as it is encoded by the
* validators in a multisig bundle
*
* @param params Parameters for the List Asset call
* @param bridgeAddress Bridge address for the appropiate network
* @returns keccak256 encoded message digest
*/
export function encodeListAssetBridgeTx(
params: EncodeListAssetParameters,
bridgeAddress: string
) {
return encodeBridgeCommand(encodeListAsset(params), bridgeAddress);
}
@@ -1,58 +0,0 @@
import { encodeUpdateAsset, encodeUpdateAssetBridgeTx } from './update-asset';
describe('Update Asset ABI encoder', () => {
it('throws if asset erc20 address is invalid', () => {
expect(() => {
encodeUpdateAsset({
assetERC20: '123',
limit: '1',
threshold: '1',
nonce: '1',
});
}).toThrowError('Asset ERC20 must be a valid address');
});
it('throws if an input is invalid', () => {
expect(() => {
encodeUpdateAsset({
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
limit: 'hello',
threshold: '1',
nonce: '1',
});
}).toThrowError(/invalid BigNumber/);
});
it('returns an ABI encoded value if inputs are valid', () => {
const EXPECTED_OUTPUT =
'0x000000000000000000000000b063f5504610ba4b8db230d9f884bfadc1e31da000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000107365745f61737365745f6c696d69747300000000000000000000000000000000';
const res = encodeUpdateAsset({
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
limit: '1',
threshold: '1',
nonce: '1',
});
expect(res).toEqual(EXPECTED_OUTPUT);
});
it('encodeUpdateAssetBridge returns a keccak256 hash of the bridge tx', () => {
const EXPECTED_OUTPUT =
'0xeb240131c4558aebfab3da0ddbea1ac0447b9f5670899af2d78795867631d877';
const res = encodeUpdateAssetBridgeTx(
{
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
limit: '1',
threshold: '1',
nonce: '1',
},
'0xb063f5504610ba4b8db230d9f884bfadc1e31da0'
);
// Magic number: keccak256 hash length + '0x'
expect(res.length).toEqual(66);
expect(res).toEqual(EXPECTED_OUTPUT);
});
});
@@ -1,65 +0,0 @@
import { defaultAbiCoder, isAddress } from 'ethers/lib/utils';
import { encodeBridgeCommand } from './bridge-command';
import type { AbiType } from './abi-types';
export const METHOD_NAME = 'set_asset_limits';
export const LIST_ASSET_ABI: AbiType[] = [
// Asset address
'address',
// Lifetime limit
'uint256',
// Withdraw threshold
'uint256',
// Nonce
'uint256',
// Contract method name
'string',
];
export interface EncodeUpdateAssetParameters {
// The ETH address of the ERC20 asset
assetERC20: string;
// The number as a string of the asset
limit: string;
// THe number-as-a-string of the withdraw threshold
threshold: string;
// The n-once supplied to the contract
nonce: string;
}
/**
* Generates an ABI encoded function call to list an asset
*
* @param EncodeListAssetParameters The arguments for the ABI call
* @returns string encoded message
*/
export function encodeUpdateAsset({
assetERC20,
limit,
threshold,
nonce,
}: EncodeUpdateAssetParameters) {
if (!isAddress(assetERC20)) {
throw new Error('Asset ERC20 must be a valid address');
}
const values = [assetERC20, limit, threshold, nonce, METHOD_NAME];
return defaultAbiCoder.encode(LIST_ASSET_ABI, values);
}
/**
* Convenience function that encodes and packs the message as it is encoded by the
* validators in a multisig bundle
*
* @param params Parameters for the List Asset call
* @param bridgeAddress Bridge address for the appropiate network
* @returns keccak256 encoded message digest
*/
export function encodeUpdateAssetBridgeTx(
params: EncodeUpdateAssetParameters,
bridgeAddress: string
) {
return encodeBridgeCommand(encodeUpdateAsset(params), bridgeAddress);
}
+2 -2
View File
@@ -1,8 +1,8 @@
# App configuration variables
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/graphql
NX_VEGA_REST=https://api.validators-testnet.vega.xyz/
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -3,66 +3,115 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type WalletDelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } };
export type WalletDelegationFieldsFragment = {
__typename?: 'Delegation';
amount: string;
epoch: number;
node: { __typename?: 'Node'; id: string; name: string };
};
export type DelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
export type DelegationsQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string }, party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } } } } | null> | null } | null } | null };
export type DelegationsQuery = {
__typename?: 'Query';
epoch: { __typename?: 'Epoch'; id: string };
party?: {
__typename?: 'Party';
id: string;
delegationsConnection?: {
__typename?: 'DelegationsConnection';
edges?: Array<{
__typename?: 'DelegationEdge';
node: {
__typename?: 'Delegation';
amount: string;
epoch: number;
node: { __typename?: 'Node'; id: string; name: string };
};
} | null> | null;
} | null;
stakingSummary: {
__typename?: 'StakingSummary';
currentStakeAvailable: string;
};
accountsConnection?: {
__typename?: 'AccountsConnection';
edges?: Array<{
__typename?: 'AccountEdge';
node: {
__typename?: 'AccountBalance';
type: Types.AccountType;
balance: string;
asset: {
__typename?: 'Asset';
name: string;
id: string;
decimals: number;
symbol: string;
source:
| { __typename: 'BuiltinAsset' }
| { __typename: 'ERC20'; contractAddress: string };
};
};
} | null> | null;
} | null;
} | null;
};
export const WalletDelegationFieldsFragmentDoc = gql`
fragment WalletDelegationFields on Delegation {
amount
node {
id
name
fragment WalletDelegationFields on Delegation {
amount
node {
id
name
}
epoch
}
epoch
}
`;
`;
export const DelegationsDocument = gql`
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
epoch {
id
}
party(id: $partyId) {
id
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...WalletDelegationFields
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
epoch {
id
}
party(id: $partyId) {
id
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...WalletDelegationFields
}
}
}
}
stakingSummary {
currentStakeAvailable
}
accountsConnection {
edges {
node {
asset {
name
id
decimals
symbol
source {
__typename
... on ERC20 {
contractAddress
stakingSummary {
currentStakeAvailable
}
accountsConnection {
edges {
node {
asset {
name
id
decimals
symbol
source {
__typename
... on ERC20 {
contractAddress
}
}
}
type
balance
}
type
balance
}
}
}
}
}
${WalletDelegationFieldsFragmentDoc}`;
${WalletDelegationFieldsFragmentDoc}
`;
/**
* __useDelegationsQuery__
@@ -81,14 +130,35 @@ export const DelegationsDocument = gql`
* },
* });
*/
export function useDelegationsQuery(baseOptions: Apollo.QueryHookOptions<DelegationsQuery, DelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<DelegationsQuery, DelegationsQueryVariables>(DelegationsDocument, options);
}
export function useDelegationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DelegationsQuery, DelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<DelegationsQuery, DelegationsQueryVariables>(DelegationsDocument, options);
}
export function useDelegationsQuery(
baseOptions: Apollo.QueryHookOptions<
DelegationsQuery,
DelegationsQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<DelegationsQuery, DelegationsQueryVariables>(
DelegationsDocument,
options
);
}
export function useDelegationsLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
DelegationsQuery,
DelegationsQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<DelegationsQuery, DelegationsQueryVariables>(
DelegationsDocument,
options
);
}
export type DelegationsQueryHookResult = ReturnType<typeof useDelegationsQuery>;
export type DelegationsLazyQueryHookResult = ReturnType<typeof useDelegationsLazyQuery>;
export type DelegationsQueryResult = Apollo.QueryResult<DelegationsQuery, DelegationsQueryVariables>;
export type DelegationsLazyQueryHookResult = ReturnType<
typeof useDelegationsLazyQuery
>;
export type DelegationsQueryResult = Apollo.QueryResult<
DelegationsQuery,
DelegationsQueryVariables
>;
@@ -7,29 +7,44 @@ export type ProposalAssetQueryVariables = Types.Exact<{
assetId: Types.Scalars['ID'];
}>;
export type ProposalAssetQuery = { __typename?: 'Query', asset?: { __typename?: 'Asset', status: Types.AssetStatus, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } | null };
export type ProposalAssetQuery = {
__typename?: 'Query';
asset?: {
__typename?: 'Asset';
status: Types.AssetStatus;
source:
| { __typename?: 'BuiltinAsset' }
| { __typename?: 'ERC20'; contractAddress: string };
} | null;
};
export type AssetListBundleQueryVariables = Types.Exact<{
assetId: Types.Scalars['ID'];
}>;
export type AssetListBundleQuery = { __typename?: 'Query', erc20ListAssetBundle?: { __typename?: 'Erc20ListAssetBundle', assetSource: string, vegaAssetId: string, nonce: string, signatures: string } | null };
export type AssetListBundleQuery = {
__typename?: 'Query';
erc20ListAssetBundle?: {
__typename?: 'Erc20ListAssetBundle';
assetSource: string;
vegaAssetId: string;
nonce: string;
signatures: string;
} | null;
};
export const ProposalAssetDocument = gql`
query ProposalAsset($assetId: ID!) {
asset(id: $assetId) {
status
source {
... on ERC20 {
contractAddress
query ProposalAsset($assetId: ID!) {
asset(id: $assetId) {
status
source {
... on ERC20 {
contractAddress
}
}
}
}
}
`;
`;
/**
* __useProposalAssetQuery__
@@ -47,27 +62,50 @@ export const ProposalAssetDocument = gql`
* },
* });
*/
export function useProposalAssetQuery(baseOptions: Apollo.QueryHookOptions<ProposalAssetQuery, ProposalAssetQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ProposalAssetQuery, ProposalAssetQueryVariables>(ProposalAssetDocument, options);
}
export function useProposalAssetLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ProposalAssetQuery, ProposalAssetQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ProposalAssetQuery, ProposalAssetQueryVariables>(ProposalAssetDocument, options);
}
export type ProposalAssetQueryHookResult = ReturnType<typeof useProposalAssetQuery>;
export type ProposalAssetLazyQueryHookResult = ReturnType<typeof useProposalAssetLazyQuery>;
export type ProposalAssetQueryResult = Apollo.QueryResult<ProposalAssetQuery, ProposalAssetQueryVariables>;
export const AssetListBundleDocument = gql`
query AssetListBundle($assetId: ID!) {
erc20ListAssetBundle(assetId: $assetId) {
assetSource
vegaAssetId
nonce
signatures
}
export function useProposalAssetQuery(
baseOptions: Apollo.QueryHookOptions<
ProposalAssetQuery,
ProposalAssetQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<ProposalAssetQuery, ProposalAssetQueryVariables>(
ProposalAssetDocument,
options
);
}
`;
export function useProposalAssetLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
ProposalAssetQuery,
ProposalAssetQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<ProposalAssetQuery, ProposalAssetQueryVariables>(
ProposalAssetDocument,
options
);
}
export type ProposalAssetQueryHookResult = ReturnType<
typeof useProposalAssetQuery
>;
export type ProposalAssetLazyQueryHookResult = ReturnType<
typeof useProposalAssetLazyQuery
>;
export type ProposalAssetQueryResult = Apollo.QueryResult<
ProposalAssetQuery,
ProposalAssetQueryVariables
>;
export const AssetListBundleDocument = gql`
query AssetListBundle($assetId: ID!) {
erc20ListAssetBundle(assetId: $assetId) {
assetSource
vegaAssetId
nonce
signatures
}
}
`;
/**
* __useAssetListBundleQuery__
@@ -85,14 +123,37 @@ export const AssetListBundleDocument = gql`
* },
* });
*/
export function useAssetListBundleQuery(baseOptions: Apollo.QueryHookOptions<AssetListBundleQuery, AssetListBundleQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<AssetListBundleQuery, AssetListBundleQueryVariables>(AssetListBundleDocument, options);
}
export function useAssetListBundleLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AssetListBundleQuery, AssetListBundleQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<AssetListBundleQuery, AssetListBundleQueryVariables>(AssetListBundleDocument, options);
}
export type AssetListBundleQueryHookResult = ReturnType<typeof useAssetListBundleQuery>;
export type AssetListBundleLazyQueryHookResult = ReturnType<typeof useAssetListBundleLazyQuery>;
export type AssetListBundleQueryResult = Apollo.QueryResult<AssetListBundleQuery, AssetListBundleQueryVariables>;
export function useAssetListBundleQuery(
baseOptions: Apollo.QueryHookOptions<
AssetListBundleQuery,
AssetListBundleQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<AssetListBundleQuery, AssetListBundleQueryVariables>(
AssetListBundleDocument,
options
);
}
export function useAssetListBundleLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
AssetListBundleQuery,
AssetListBundleQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
AssetListBundleQuery,
AssetListBundleQueryVariables
>(AssetListBundleDocument, options);
}
export type AssetListBundleQueryHookResult = ReturnType<
typeof useAssetListBundleQuery
>;
export type AssetListBundleLazyQueryHookResult = ReturnType<
typeof useAssetListBundleLazyQuery
>;
export type AssetListBundleQueryResult = Apollo.QueryResult<
AssetListBundleQuery,
AssetListBundleQueryVariables
>;
@@ -7,20 +7,28 @@ export type VoteButtonsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type VoteButtonsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string } } | null };
export type VoteButtonsQuery = {
__typename?: 'Query';
party?: {
__typename?: 'Party';
id: string;
stakingSummary: {
__typename?: 'StakingSummary';
currentStakeAvailable: string;
};
} | null;
};
export const VoteButtonsDocument = gql`
query VoteButtons($partyId: ID!) {
party(id: $partyId) {
id
stakingSummary {
currentStakeAvailable
query VoteButtons($partyId: ID!) {
party(id: $partyId) {
id
stakingSummary {
currentStakeAvailable
}
}
}
}
`;
`;
/**
* __useVoteButtonsQuery__
@@ -38,14 +46,35 @@ export const VoteButtonsDocument = gql`
* },
* });
*/
export function useVoteButtonsQuery(baseOptions: Apollo.QueryHookOptions<VoteButtonsQuery, VoteButtonsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<VoteButtonsQuery, VoteButtonsQueryVariables>(VoteButtonsDocument, options);
}
export function useVoteButtonsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<VoteButtonsQuery, VoteButtonsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<VoteButtonsQuery, VoteButtonsQueryVariables>(VoteButtonsDocument, options);
}
export function useVoteButtonsQuery(
baseOptions: Apollo.QueryHookOptions<
VoteButtonsQuery,
VoteButtonsQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<VoteButtonsQuery, VoteButtonsQueryVariables>(
VoteButtonsDocument,
options
);
}
export function useVoteButtonsLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
VoteButtonsQuery,
VoteButtonsQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<VoteButtonsQuery, VoteButtonsQueryVariables>(
VoteButtonsDocument,
options
);
}
export type VoteButtonsQueryHookResult = ReturnType<typeof useVoteButtonsQuery>;
export type VoteButtonsLazyQueryHookResult = ReturnType<typeof useVoteButtonsLazyQuery>;
export type VoteButtonsQueryResult = Apollo.QueryResult<VoteButtonsQuery, VoteButtonsQueryVariables>;
export type VoteButtonsLazyQueryHookResult = ReturnType<
typeof useVoteButtonsLazyQuery
>;
export type VoteButtonsQueryResult = Apollo.QueryResult<
VoteButtonsQuery,
VoteButtonsQueryVariables
>;
@@ -7,27 +7,41 @@ export type UserVoteQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type UserVoteQuery = { __typename?: 'Query', party?: { __typename?: 'Party', votesConnection?: { __typename?: 'ProposalVoteConnection', edges?: Array<{ __typename?: 'ProposalVoteEdge', node: { __typename?: 'ProposalVote', proposalId: string, vote: { __typename?: 'Vote', value: Types.VoteValue, datetime: any } } }> | null } | null } | null };
export type UserVoteQuery = {
__typename?: 'Query';
party?: {
__typename?: 'Party';
votesConnection?: {
__typename?: 'ProposalVoteConnection';
edges?: Array<{
__typename?: 'ProposalVoteEdge';
node: {
__typename?: 'ProposalVote';
proposalId: string;
vote: { __typename?: 'Vote'; value: Types.VoteValue; datetime: any };
};
}> | null;
} | null;
} | null;
};
export const UserVoteDocument = gql`
query UserVote($partyId: ID!) {
party(id: $partyId) {
votesConnection {
edges {
node {
proposalId
vote {
value
datetime
query UserVote($partyId: ID!) {
party(id: $partyId) {
votesConnection {
edges {
node {
proposalId
vote {
value
datetime
}
}
}
}
}
}
}
`;
`;
/**
* __useUserVoteQuery__
@@ -45,14 +59,32 @@ export const UserVoteDocument = gql`
* },
* });
*/
export function useUserVoteQuery(baseOptions: Apollo.QueryHookOptions<UserVoteQuery, UserVoteQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<UserVoteQuery, UserVoteQueryVariables>(UserVoteDocument, options);
}
export function useUserVoteLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<UserVoteQuery, UserVoteQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<UserVoteQuery, UserVoteQueryVariables>(UserVoteDocument, options);
}
export function useUserVoteQuery(
baseOptions: Apollo.QueryHookOptions<UserVoteQuery, UserVoteQueryVariables>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<UserVoteQuery, UserVoteQueryVariables>(
UserVoteDocument,
options
);
}
export function useUserVoteLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
UserVoteQuery,
UserVoteQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<UserVoteQuery, UserVoteQueryVariables>(
UserVoteDocument,
options
);
}
export type UserVoteQueryHookResult = ReturnType<typeof useUserVoteQuery>;
export type UserVoteLazyQueryHookResult = ReturnType<typeof useUserVoteLazyQuery>;
export type UserVoteQueryResult = Apollo.QueryResult<UserVoteQuery, UserVoteQueryVariables>;
export type UserVoteLazyQueryHookResult = ReturnType<
typeof useUserVoteLazyQuery
>;
export type UserVoteQueryResult = Apollo.QueryResult<
UserVoteQuery,
UserVoteQueryVariables
>;
File diff suppressed because one or more lines are too long
@@ -3,106 +3,279 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } };
export type ProposalFieldsFragment = {
__typename?: 'Proposal';
id?: string | null;
reference: string;
state: Types.ProposalState;
datetime: any;
rejectionReason?: Types.ProposalRejectionReason | null;
errorDetails?: string | null;
rationale: {
__typename?: 'ProposalRationale';
title: string;
description: string;
};
party: { __typename?: 'Party'; id: string };
terms: {
__typename?: 'ProposalTerms';
closingDatetime: any;
enactmentDatetime?: any | null;
change:
| {
__typename: 'NewAsset';
name: string;
symbol: string;
decimals: number;
quantum: string;
source:
| { __typename?: 'BuiltinAsset'; maxFaucetAmountMint: string }
| {
__typename?: 'ERC20';
contractAddress: string;
withdrawThreshold: string;
lifetimeLimit: string;
};
}
| { __typename?: 'NewFreeform' }
| {
__typename?: 'NewMarket';
instrument: {
__typename?: 'InstrumentConfiguration';
name: string;
code: string;
futureProduct?: {
__typename?: 'FutureProduct';
settlementAsset: { __typename?: 'Asset'; symbol: string };
} | null;
};
}
| {
__typename?: 'UpdateAsset';
quantum: string;
assetId: string;
source: {
__typename?: 'UpdateERC20';
lifetimeLimit: string;
withdrawThreshold: string;
};
}
| { __typename?: 'UpdateMarket'; marketId: string }
| {
__typename?: 'UpdateNetworkParameter';
networkParameter: {
__typename?: 'NetworkParameter';
key: string;
value: string;
};
};
};
votes: {
__typename?: 'ProposalVotes';
yes: {
__typename?: 'ProposalVoteSide';
totalTokens: string;
totalNumber: string;
totalEquityLikeShareWeight: string;
};
no: {
__typename?: 'ProposalVoteSide';
totalTokens: string;
totalNumber: string;
totalEquityLikeShareWeight: string;
};
};
};
export type ProposalsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ProposalsQueryVariables = Types.Exact<{ [key: string]: never }>;
export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null };
export type ProposalsQuery = {
__typename?: 'Query';
proposalsConnection?: {
__typename?: 'ProposalsConnection';
edges?: Array<{
__typename?: 'ProposalEdge';
node: {
__typename?: 'Proposal';
id?: string | null;
reference: string;
state: Types.ProposalState;
datetime: any;
rejectionReason?: Types.ProposalRejectionReason | null;
errorDetails?: string | null;
rationale: {
__typename?: 'ProposalRationale';
title: string;
description: string;
};
party: { __typename?: 'Party'; id: string };
terms: {
__typename?: 'ProposalTerms';
closingDatetime: any;
enactmentDatetime?: any | null;
change:
| {
__typename: 'NewAsset';
name: string;
symbol: string;
decimals: number;
quantum: string;
source:
| { __typename?: 'BuiltinAsset'; maxFaucetAmountMint: string }
| {
__typename?: 'ERC20';
contractAddress: string;
withdrawThreshold: string;
lifetimeLimit: string;
};
}
| { __typename?: 'NewFreeform' }
| {
__typename?: 'NewMarket';
instrument: {
__typename?: 'InstrumentConfiguration';
name: string;
code: string;
futureProduct?: {
__typename?: 'FutureProduct';
settlementAsset: { __typename?: 'Asset'; symbol: string };
} | null;
};
}
| {
__typename?: 'UpdateAsset';
quantum: string;
assetId: string;
source: {
__typename?: 'UpdateERC20';
lifetimeLimit: string;
withdrawThreshold: string;
};
}
| { __typename?: 'UpdateMarket'; marketId: string }
| {
__typename?: 'UpdateNetworkParameter';
networkParameter: {
__typename?: 'NetworkParameter';
key: string;
value: string;
};
};
};
votes: {
__typename?: 'ProposalVotes';
yes: {
__typename?: 'ProposalVoteSide';
totalTokens: string;
totalNumber: string;
totalEquityLikeShareWeight: string;
};
no: {
__typename?: 'ProposalVoteSide';
totalTokens: string;
totalNumber: string;
totalEquityLikeShareWeight: string;
};
};
};
} | null> | null;
} | null;
};
export const ProposalFieldsFragmentDoc = gql`
fragment ProposalFields on Proposal {
id
rationale {
title
description
}
reference
state
datetime
rejectionReason
party {
fragment ProposalFields on Proposal {
id
}
errorDetails
terms {
closingDatetime
enactmentDatetime
change {
... on NewMarket {
instrument {
rationale {
title
description
}
reference
state
datetime
rejectionReason
party {
id
}
errorDetails
terms {
closingDatetime
enactmentDatetime
change {
... on NewMarket {
instrument {
name
code
futureProduct {
settlementAsset {
symbol
}
}
}
}
... on UpdateMarket {
marketId
}
... on NewAsset {
__typename
name
code
futureProduct {
settlementAsset {
symbol
symbol
decimals
quantum
source {
... on BuiltinAsset {
maxFaucetAmountMint
}
... on ERC20 {
contractAddress
withdrawThreshold
lifetimeLimit
}
}
}
... on UpdateNetworkParameter {
networkParameter {
key
value
}
}
... on UpdateAsset {
quantum
assetId
source {
... on UpdateERC20 {
lifetimeLimit
withdrawThreshold
}
}
}
}
... on UpdateMarket {
marketId
}
votes {
yes {
totalTokens
totalNumber
totalEquityLikeShareWeight
}
... on NewAsset {
__typename
name
symbol
decimals
quantum
source {
... on BuiltinAsset {
maxFaucetAmountMint
}
... on ERC20 {
contractAddress
withdrawThreshold
lifetimeLimit
}
}
}
... on UpdateNetworkParameter {
networkParameter {
key
value
}
}
... on UpdateAsset {
quantum
assetId
source {
... on UpdateERC20 {
lifetimeLimit
withdrawThreshold
}
}
no {
totalTokens
totalNumber
totalEquityLikeShareWeight
}
}
}
votes {
yes {
totalTokens
totalNumber
totalEquityLikeShareWeight
}
no {
totalTokens
totalNumber
totalEquityLikeShareWeight
}
}
}
`;
`;
export const ProposalsDocument = gql`
query Proposals {
proposalsConnection {
edges {
node {
...ProposalFields
query Proposals {
proposalsConnection {
edges {
node {
...ProposalFields
}
}
}
}
}
${ProposalFieldsFragmentDoc}`;
${ProposalFieldsFragmentDoc}
`;
/**
* __useProposalsQuery__
@@ -119,14 +292,32 @@ export const ProposalsDocument = gql`
* },
* });
*/
export function useProposalsQuery(baseOptions?: Apollo.QueryHookOptions<ProposalsQuery, ProposalsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ProposalsQuery, ProposalsQueryVariables>(ProposalsDocument, options);
}
export function useProposalsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ProposalsQuery, ProposalsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ProposalsQuery, ProposalsQueryVariables>(ProposalsDocument, options);
}
export function useProposalsQuery(
baseOptions?: Apollo.QueryHookOptions<ProposalsQuery, ProposalsQueryVariables>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<ProposalsQuery, ProposalsQueryVariables>(
ProposalsDocument,
options
);
}
export function useProposalsLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
ProposalsQuery,
ProposalsQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<ProposalsQuery, ProposalsQueryVariables>(
ProposalsDocument,
options
);
}
export type ProposalsQueryHookResult = ReturnType<typeof useProposalsQuery>;
export type ProposalsLazyQueryHookResult = ReturnType<typeof useProposalsLazyQuery>;
export type ProposalsQueryResult = Apollo.QueryResult<ProposalsQuery, ProposalsQueryVariables>;
export type ProposalsLazyQueryHookResult = ReturnType<
typeof useProposalsLazyQuery
>;
export type ProposalsQueryResult = Apollo.QueryResult<
ProposalsQuery,
ProposalsQueryVariables
>;
@@ -3,29 +3,45 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ProposalMarketsQueryQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ProposalMarketsQueryQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string } } } }> } | null };
export type ProposalMarketsQueryQueryVariables = Types.Exact<{
[key: string]: never;
}>;
export type ProposalMarketsQueryQuery = {
__typename?: 'Query';
marketsConnection?: {
__typename?: 'MarketConnection';
edges: Array<{
__typename?: 'MarketEdge';
node: {
__typename?: 'Market';
id: string;
tradableInstrument: {
__typename?: 'TradableInstrument';
instrument: { __typename?: 'Instrument'; name: string; code: string };
};
};
}>;
} | null;
};
export const ProposalMarketsQueryDocument = gql`
query ProposalMarketsQuery {
marketsConnection {
edges {
node {
id
tradableInstrument {
instrument {
name
code
query ProposalMarketsQuery {
marketsConnection {
edges {
node {
id
tradableInstrument {
instrument {
name
code
}
}
}
}
}
}
}
`;
`;
/**
* __useProposalMarketsQueryQuery__
@@ -42,14 +58,37 @@ export const ProposalMarketsQueryDocument = gql`
* },
* });
*/
export function useProposalMarketsQueryQuery(baseOptions?: Apollo.QueryHookOptions<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>(ProposalMarketsQueryDocument, options);
}
export function useProposalMarketsQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>(ProposalMarketsQueryDocument, options);
}
export type ProposalMarketsQueryQueryHookResult = ReturnType<typeof useProposalMarketsQueryQuery>;
export type ProposalMarketsQueryLazyQueryHookResult = ReturnType<typeof useProposalMarketsQueryLazyQuery>;
export type ProposalMarketsQueryQueryResult = Apollo.QueryResult<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>;
export function useProposalMarketsQueryQuery(
baseOptions?: Apollo.QueryHookOptions<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>(ProposalMarketsQueryDocument, options);
}
export function useProposalMarketsQueryLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>(ProposalMarketsQueryDocument, options);
}
export type ProposalMarketsQueryQueryHookResult = ReturnType<
typeof useProposalMarketsQueryQuery
>;
export type ProposalMarketsQueryLazyQueryHookResult = ReturnType<
typeof useProposalMarketsQueryLazyQuery
>;
export type ProposalMarketsQueryQueryResult = Apollo.QueryResult<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>;
@@ -7,30 +7,52 @@ export type PreviousEpochQueryVariables = Types.Exact<{
epochId?: Types.InputMaybe<Types.Scalars['ID']>;
}>;
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string } | null, rankingScore: { __typename?: 'RankingScore', performanceScore: string } } } | null> | null } | null } };
export type PreviousEpochQuery = {
__typename?: 'Query';
epoch: {
__typename?: 'Epoch';
id: string;
validatorsConnection?: {
__typename?: 'NodesConnection';
edges?: Array<{
__typename?: 'NodeEdge';
node: {
__typename?: 'Node';
id: string;
rewardScore?: {
__typename?: 'RewardScore';
rawValidatorScore: string;
} | null;
rankingScore: {
__typename?: 'RankingScore';
performanceScore: string;
};
};
} | null> | null;
} | null;
};
};
export const PreviousEpochDocument = gql`
query PreviousEpoch($epochId: ID) {
epoch(id: $epochId) {
id
validatorsConnection {
edges {
node {
id
rewardScore {
rawValidatorScore
}
rankingScore {
performanceScore
query PreviousEpoch($epochId: ID) {
epoch(id: $epochId) {
id
validatorsConnection {
edges {
node {
id
rewardScore {
rawValidatorScore
}
rankingScore {
performanceScore
}
}
}
}
}
}
}
`;
`;
/**
* __usePreviousEpochQuery__
@@ -48,14 +70,37 @@ export const PreviousEpochDocument = gql`
* },
* });
*/
export function usePreviousEpochQuery(baseOptions?: Apollo.QueryHookOptions<PreviousEpochQuery, PreviousEpochQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PreviousEpochQuery, PreviousEpochQueryVariables>(PreviousEpochDocument, options);
}
export function usePreviousEpochLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PreviousEpochQuery, PreviousEpochQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PreviousEpochQuery, PreviousEpochQueryVariables>(PreviousEpochDocument, options);
}
export type PreviousEpochQueryHookResult = ReturnType<typeof usePreviousEpochQuery>;
export type PreviousEpochLazyQueryHookResult = ReturnType<typeof usePreviousEpochLazyQuery>;
export type PreviousEpochQueryResult = Apollo.QueryResult<PreviousEpochQuery, PreviousEpochQueryVariables>;
export function usePreviousEpochQuery(
baseOptions?: Apollo.QueryHookOptions<
PreviousEpochQuery,
PreviousEpochQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<PreviousEpochQuery, PreviousEpochQueryVariables>(
PreviousEpochDocument,
options
);
}
export function usePreviousEpochLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
PreviousEpochQuery,
PreviousEpochQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<PreviousEpochQuery, PreviousEpochQueryVariables>(
PreviousEpochDocument,
options
);
}
export type PreviousEpochQueryHookResult = ReturnType<
typeof usePreviousEpochQuery
>;
export type PreviousEpochLazyQueryHookResult = ReturnType<
typeof usePreviousEpochLazyQuery
>;
export type PreviousEpochQueryResult = Apollo.QueryResult<
PreviousEpochQuery,
PreviousEpochQueryVariables
>;
@@ -3,38 +3,64 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type LinkingsFieldsFragment = { __typename?: 'StakeLinking', id: string, txHash: string, status: Types.StakeLinkingStatus };
export type LinkingsFieldsFragment = {
__typename?: 'StakeLinking';
id: string;
txHash: string;
status: Types.StakeLinkingStatus;
};
export type PartyStakeLinkingsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type PartyStakeLinkingsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', linkings: { __typename?: 'StakesConnection', edges?: Array<{ __typename?: 'StakeLinkingEdge', node: { __typename?: 'StakeLinking', id: string, txHash: string, status: Types.StakeLinkingStatus } } | null> | null } } } | null };
export type PartyStakeLinkingsQuery = {
__typename?: 'Query';
party?: {
__typename?: 'Party';
id: string;
stakingSummary: {
__typename?: 'StakingSummary';
linkings: {
__typename?: 'StakesConnection';
edges?: Array<{
__typename?: 'StakeLinkingEdge';
node: {
__typename?: 'StakeLinking';
id: string;
txHash: string;
status: Types.StakeLinkingStatus;
};
} | null> | null;
};
};
} | null;
};
export const LinkingsFieldsFragmentDoc = gql`
fragment LinkingsFields on StakeLinking {
id
txHash
status
}
`;
export const PartyStakeLinkingsDocument = gql`
query PartyStakeLinkings($partyId: ID!) {
party(id: $partyId) {
fragment LinkingsFields on StakeLinking {
id
stakingSummary {
linkings {
edges {
node {
...LinkingsFields
txHash
status
}
`;
export const PartyStakeLinkingsDocument = gql`
query PartyStakeLinkings($partyId: ID!) {
party(id: $partyId) {
id
stakingSummary {
linkings {
edges {
node {
...LinkingsFields
}
}
}
}
}
}
}
${LinkingsFieldsFragmentDoc}`;
${LinkingsFieldsFragmentDoc}
`;
/**
* __usePartyStakeLinkingsQuery__
@@ -52,14 +78,37 @@ export const PartyStakeLinkingsDocument = gql`
* },
* });
*/
export function usePartyStakeLinkingsQuery(baseOptions: Apollo.QueryHookOptions<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>(PartyStakeLinkingsDocument, options);
}
export function usePartyStakeLinkingsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>(PartyStakeLinkingsDocument, options);
}
export type PartyStakeLinkingsQueryHookResult = ReturnType<typeof usePartyStakeLinkingsQuery>;
export type PartyStakeLinkingsLazyQueryHookResult = ReturnType<typeof usePartyStakeLinkingsLazyQuery>;
export type PartyStakeLinkingsQueryResult = Apollo.QueryResult<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>;
export function usePartyStakeLinkingsQuery(
baseOptions: Apollo.QueryHookOptions<
PartyStakeLinkingsQuery,
PartyStakeLinkingsQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<
PartyStakeLinkingsQuery,
PartyStakeLinkingsQueryVariables
>(PartyStakeLinkingsDocument, options);
}
export function usePartyStakeLinkingsLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
PartyStakeLinkingsQuery,
PartyStakeLinkingsQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
PartyStakeLinkingsQuery,
PartyStakeLinkingsQueryVariables
>(PartyStakeLinkingsDocument, options);
}
export type PartyStakeLinkingsQueryHookResult = ReturnType<
typeof usePartyStakeLinkingsQuery
>;
export type PartyStakeLinkingsLazyQueryHookResult = ReturnType<
typeof usePartyStakeLinkingsLazyQuery
>;
export type PartyStakeLinkingsQueryResult = Apollo.QueryResult<
PartyStakeLinkingsQuery,
PartyStakeLinkingsQueryVariables
>;
+116 -47
View File
@@ -3,54 +3,110 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type NodesFragmentFragment = { __typename?: 'Node', avatarUrl?: string | null, id: string, name: string, pubkey: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } };
export type NodesFragmentFragment = {
__typename?: 'Node';
avatarUrl?: string | null;
id: string;
name: string;
pubkey: string;
stakedByOperator: string;
stakedByDelegates: string;
stakedTotal: string;
pendingStake: string;
rankingScore: {
__typename?: 'RankingScore';
rankingScore: string;
stakeScore: string;
performanceScore: string;
votingPower: string;
status: Types.ValidatorStatus;
};
};
export type NodesQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type NodesQueryVariables = Types.Exact<{ [key: string]: never }>;
export type NodesQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } }, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', avatarUrl?: string | null, id: string, name: string, pubkey: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string } | null };
export type NodesQuery = {
__typename?: 'Query';
epoch: {
__typename?: 'Epoch';
id: string;
timestamps: {
__typename?: 'EpochTimestamps';
start?: any | null;
end?: any | null;
expiry?: any | null;
};
};
nodesConnection: {
__typename?: 'NodesConnection';
edges?: Array<{
__typename?: 'NodeEdge';
node: {
__typename?: 'Node';
avatarUrl?: string | null;
id: string;
name: string;
pubkey: string;
stakedByOperator: string;
stakedByDelegates: string;
stakedTotal: string;
pendingStake: string;
rankingScore: {
__typename?: 'RankingScore';
rankingScore: string;
stakeScore: string;
performanceScore: string;
votingPower: string;
status: Types.ValidatorStatus;
};
};
} | null> | null;
};
nodeData?: { __typename?: 'NodeData'; stakedTotal: string } | null;
};
export const NodesFragmentFragmentDoc = gql`
fragment NodesFragment on Node {
avatarUrl
id
name
pubkey
stakedByOperator
stakedByDelegates
stakedTotal
pendingStake
rankingScore {
rankingScore
stakeScore
performanceScore
votingPower
status
}
}
`;
export const NodesDocument = gql`
query Nodes {
epoch {
fragment NodesFragment on Node {
avatarUrl
id
timestamps {
start
end
expiry
name
pubkey
stakedByOperator
stakedByDelegates
stakedTotal
pendingStake
rankingScore {
rankingScore
stakeScore
performanceScore
votingPower
status
}
}
nodesConnection {
edges {
node {
...NodesFragment
`;
export const NodesDocument = gql`
query Nodes {
epoch {
id
timestamps {
start
end
expiry
}
}
nodesConnection {
edges {
node {
...NodesFragment
}
}
}
nodeData {
stakedTotal
}
}
nodeData {
stakedTotal
}
}
${NodesFragmentFragmentDoc}`;
${NodesFragmentFragmentDoc}
`;
/**
* __useNodesQuery__
@@ -67,14 +123,27 @@ export const NodesDocument = gql`
* },
* });
*/
export function useNodesQuery(baseOptions?: Apollo.QueryHookOptions<NodesQuery, NodesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<NodesQuery, NodesQueryVariables>(NodesDocument, options);
}
export function useNodesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<NodesQuery, NodesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<NodesQuery, NodesQueryVariables>(NodesDocument, options);
}
export function useNodesQuery(
baseOptions?: Apollo.QueryHookOptions<NodesQuery, NodesQueryVariables>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<NodesQuery, NodesQueryVariables>(
NodesDocument,
options
);
}
export function useNodesLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<NodesQuery, NodesQueryVariables>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<NodesQuery, NodesQueryVariables>(
NodesDocument,
options
);
}
export type NodesQueryHookResult = ReturnType<typeof useNodesQuery>;
export type NodesLazyQueryHookResult = ReturnType<typeof useNodesLazyQuery>;
export type NodesQueryResult = Apollo.QueryResult<NodesQuery, NodesQueryVariables>;
export type NodesQueryResult = Apollo.QueryResult<
NodesQuery,
NodesQueryVariables
>;
@@ -3,42 +3,66 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type StakingDelegationsFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } };
export type StakingDelegationsFieldsFragment = {
__typename?: 'Delegation';
amount: string;
epoch: number;
node: { __typename?: 'Node'; id: string };
};
export type PartyDelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
export type PartyDelegationsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string } };
export type PartyDelegationsQuery = {
__typename?: 'Query';
party?: {
__typename?: 'Party';
id: string;
delegationsConnection?: {
__typename?: 'DelegationsConnection';
edges?: Array<{
__typename?: 'DelegationEdge';
node: {
__typename?: 'Delegation';
amount: string;
epoch: number;
node: { __typename?: 'Node'; id: string };
};
} | null> | null;
} | null;
} | null;
epoch: { __typename?: 'Epoch'; id: string };
};
export const StakingDelegationsFieldsFragmentDoc = gql`
fragment StakingDelegationsFields on Delegation {
amount
node {
id
fragment StakingDelegationsFields on Delegation {
amount
node {
id
}
epoch
}
epoch
}
`;
`;
export const PartyDelegationsDocument = gql`
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...StakingDelegationsFields
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...StakingDelegationsFields
}
}
}
}
epoch {
id
}
}
epoch {
id
}
}
${StakingDelegationsFieldsFragmentDoc}`;
${StakingDelegationsFieldsFragmentDoc}
`;
/**
* __usePartyDelegationsQuery__
@@ -57,14 +81,37 @@ export const PartyDelegationsDocument = gql`
* },
* });
*/
export function usePartyDelegationsQuery(baseOptions: Apollo.QueryHookOptions<PartyDelegationsQuery, PartyDelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(PartyDelegationsDocument, options);
}
export function usePartyDelegationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyDelegationsQuery, PartyDelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(PartyDelegationsDocument, options);
}
export type PartyDelegationsQueryHookResult = ReturnType<typeof usePartyDelegationsQuery>;
export type PartyDelegationsLazyQueryHookResult = ReturnType<typeof usePartyDelegationsLazyQuery>;
export type PartyDelegationsQueryResult = Apollo.QueryResult<PartyDelegationsQuery, PartyDelegationsQueryVariables>;
export function usePartyDelegationsQuery(
baseOptions: Apollo.QueryHookOptions<
PartyDelegationsQuery,
PartyDelegationsQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(
PartyDelegationsDocument,
options
);
}
export function usePartyDelegationsLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
PartyDelegationsQuery,
PartyDelegationsQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
PartyDelegationsQuery,
PartyDelegationsQueryVariables
>(PartyDelegationsDocument, options);
}
export type PartyDelegationsQueryHookResult = ReturnType<
typeof usePartyDelegationsQuery
>;
export type PartyDelegationsLazyQueryHookResult = ReturnType<
typeof usePartyDelegationsLazyQuery
>;
export type PartyDelegationsQueryResult = Apollo.QueryResult<
PartyDelegationsQuery,
PartyDelegationsQueryVariables
>;
+180 -69
View File
@@ -3,84 +3,182 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type StakingNodeFieldsFragment = { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } };
export type StakingNodeFieldsFragment = {
__typename?: 'Node';
id: string;
name: string;
pubkey: string;
infoUrl: string;
location: string;
ethereumAddress: string;
stakedByOperator: string;
stakedByDelegates: string;
stakedTotal: string;
pendingStake: string;
epochData?: {
__typename?: 'EpochData';
total: number;
offline: number;
online: number;
} | null;
rankingScore: {
__typename?: 'RankingScore';
rankingScore: string;
stakeScore: string;
performanceScore: string;
votingPower: string;
status: Types.ValidatorStatus;
};
};
export type StakingQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
export type StakingQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } }, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string, totalNodes: number, inactiveNodes: number, uptime: number } | null };
export type StakingQuery = {
__typename?: 'Query';
party?: {
__typename?: 'Party';
id: string;
stakingSummary: {
__typename?: 'StakingSummary';
currentStakeAvailable: string;
};
delegationsConnection?: {
__typename?: 'DelegationsConnection';
edges?: Array<{
__typename?: 'DelegationEdge';
node: {
__typename?: 'Delegation';
amount: string;
epoch: number;
node: { __typename?: 'Node'; id: string };
};
} | null> | null;
} | null;
} | null;
epoch: {
__typename?: 'Epoch';
id: string;
timestamps: {
__typename?: 'EpochTimestamps';
start?: any | null;
end?: any | null;
expiry?: any | null;
};
};
nodesConnection: {
__typename?: 'NodesConnection';
edges?: Array<{
__typename?: 'NodeEdge';
node: {
__typename?: 'Node';
id: string;
name: string;
pubkey: string;
infoUrl: string;
location: string;
ethereumAddress: string;
stakedByOperator: string;
stakedByDelegates: string;
stakedTotal: string;
pendingStake: string;
epochData?: {
__typename?: 'EpochData';
total: number;
offline: number;
online: number;
} | null;
rankingScore: {
__typename?: 'RankingScore';
rankingScore: string;
stakeScore: string;
performanceScore: string;
votingPower: string;
status: Types.ValidatorStatus;
};
};
} | null> | null;
};
nodeData?: {
__typename?: 'NodeData';
stakedTotal: string;
totalNodes: number;
inactiveNodes: number;
uptime: number;
} | null;
};
export const StakingNodeFieldsFragmentDoc = gql`
fragment StakingNodeFields on Node {
id
name
pubkey
infoUrl
location
ethereumAddress
stakedByOperator
stakedByDelegates
stakedTotal
pendingStake
epochData {
total
offline
online
}
rankingScore {
rankingScore
stakeScore
performanceScore
votingPower
status
}
}
`;
export const StakingDocument = gql`
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
fragment StakingNodeFields on Node {
id
stakingSummary {
currentStakeAvailable
name
pubkey
infoUrl
location
ethereumAddress
stakedByOperator
stakedByDelegates
stakedTotal
pendingStake
epochData {
total
offline
online
}
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
amount
epoch
rankingScore {
rankingScore
stakeScore
performanceScore
votingPower
status
}
}
`;
export const StakingDocument = gql`
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
stakingSummary {
currentStakeAvailable
}
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
id
amount
epoch
node {
id
}
}
}
}
}
}
epoch {
id
timestamps {
start
end
expiry
}
}
nodesConnection {
edges {
node {
...StakingNodeFields
epoch {
id
timestamps {
start
end
expiry
}
}
nodesConnection {
edges {
node {
...StakingNodeFields
}
}
}
nodeData {
stakedTotal
totalNodes
inactiveNodes
uptime
}
}
nodeData {
stakedTotal
totalNodes
inactiveNodes
uptime
}
}
${StakingNodeFieldsFragmentDoc}`;
${StakingNodeFieldsFragmentDoc}
`;
/**
* __useStakingQuery__
@@ -99,14 +197,27 @@ export const StakingDocument = gql`
* },
* });
*/
export function useStakingQuery(baseOptions: Apollo.QueryHookOptions<StakingQuery, StakingQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<StakingQuery, StakingQueryVariables>(StakingDocument, options);
}
export function useStakingLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<StakingQuery, StakingQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<StakingQuery, StakingQueryVariables>(StakingDocument, options);
}
export function useStakingQuery(
baseOptions: Apollo.QueryHookOptions<StakingQuery, StakingQueryVariables>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<StakingQuery, StakingQueryVariables>(
StakingDocument,
options
);
}
export function useStakingLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<StakingQuery, StakingQueryVariables>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<StakingQuery, StakingQueryVariables>(
StakingDocument,
options
);
}
export type StakingQueryHookResult = ReturnType<typeof useStakingQuery>;
export type StakingLazyQueryHookResult = ReturnType<typeof useStakingLazyQuery>;
export type StakingQueryResult = Apollo.QueryResult<StakingQuery, StakingQueryVariables>;
export type StakingQueryResult = Apollo.QueryResult<
StakingQuery,
StakingQueryVariables
>;
+38 -19
View File
@@ -3,19 +3,20 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type NodeDataQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type NodeDataQuery = { __typename?: 'Query', nodeData?: { __typename?: 'NodeData', stakedTotal: string } | null };
export type NodeDataQueryVariables = Types.Exact<{ [key: string]: never }>;
export type NodeDataQuery = {
__typename?: 'Query';
nodeData?: { __typename?: 'NodeData'; stakedTotal: string } | null;
};
export const NodeDataDocument = gql`
query NodeData {
nodeData {
stakedTotal
query NodeData {
nodeData {
stakedTotal
}
}
}
`;
`;
/**
* __useNodeDataQuery__
@@ -32,14 +33,32 @@ export const NodeDataDocument = gql`
* },
* });
*/
export function useNodeDataQuery(baseOptions?: Apollo.QueryHookOptions<NodeDataQuery, NodeDataQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<NodeDataQuery, NodeDataQueryVariables>(NodeDataDocument, options);
}
export function useNodeDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<NodeDataQuery, NodeDataQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<NodeDataQuery, NodeDataQueryVariables>(NodeDataDocument, options);
}
export function useNodeDataQuery(
baseOptions?: Apollo.QueryHookOptions<NodeDataQuery, NodeDataQueryVariables>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<NodeDataQuery, NodeDataQueryVariables>(
NodeDataDocument,
options
);
}
export function useNodeDataLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
NodeDataQuery,
NodeDataQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<NodeDataQuery, NodeDataQueryVariables>(
NodeDataDocument,
options
);
}
export type NodeDataQueryHookResult = ReturnType<typeof useNodeDataQuery>;
export type NodeDataLazyQueryHookResult = ReturnType<typeof useNodeDataLazyQuery>;
export type NodeDataQueryResult = Apollo.QueryResult<NodeDataQuery, NodeDataQueryVariables>;
export type NodeDataLazyQueryHookResult = ReturnType<
typeof useNodeDataLazyQuery
>;
export type NodeDataQueryResult = Apollo.QueryResult<
NodeDataQuery,
NodeDataQueryVariables
>;
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=VALIDATOR_TESTNET
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,3 @@
{
"hosts": [
"https://api-validators-testnet.vega.rocks/graphql",
"https://vega-testnet.anyvalid.com/query"
]
"hosts": ["https://api.validators-testnet.vega.xyz/graphql"]
}
@@ -131,6 +131,7 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
cy.get('p.col-span-1').contains('Within 43,200 seconds');
validateMarketDataRow(0, 'Highest Price', '7.97323 ');
validateMarketDataRow(1, 'Lowest Price', '6.54701 ');
validateMarketDataRow(2, 'Reference Price', '7.22625 ');
});
it('liquidity monitoring parameters displayed', () => {
@@ -22,25 +22,24 @@ describe('accounts', { tags: '@smoke' }, () => {
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="accounts-actions"]')
.should('have.text', 'DepositWithdraw');
.find('[col-id="breakdown"] [data-testid="breakdown"]')
.should('have.text', 'Breakdown');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[data-testid="deposit"]')
.find('[col-id="breakdown"] [data-testid="deposit"]')
.should('have.text', 'Deposit');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="accounts-actions"] [data-testid="withdraw"]')
.find('[col-id="breakdown"] [data-testid="withdraw"]')
.should('have.text', 'Withdraw');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="total"]')
.find('[col-id="deposited"]')
.should('have.text', '100,001.01');
});
describe('sorting by ag-grid columns should work well', () => {
it('sorting by asset', () => {
cy.getByTestId('Collateral').click();
@@ -79,7 +78,7 @@ describe('accounts', { tags: '@smoke' }, () => {
'1,000.00',
];
checkSorting(
'total',
'deposited',
marketsSortedDefault,
marketsSortedAsc,
marketsSortedDesc
@@ -88,27 +87,9 @@ describe('accounts', { tags: '@smoke' }, () => {
it('sorting by used', () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = [
'0.000.00%',
'1.010.00%',
'0.010.00%',
'0.000.00%',
'0.000.00%',
];
const marketsSortedAsc = [
'0.000.00%',
'0.000.00%',
'0.000.00%',
'0.010.00%',
'1.010.00%',
];
const marketsSortedDesc = [
'1.010.00%',
'0.010.00%',
'0.000.00%',
'0.000.00%',
'0.000.00%',
];
const marketsSortedDefault = ['0.00', '1.01', '0.01', '0.00', '0.00'];
const marketsSortedAsc = ['0.00', '0.00', '0.00', '0.01', '1.01'];
const marketsSortedDesc = ['1.01', '0.01', '0.00', '0.00', '0.00'];
checkSorting(
'used',
marketsSortedDefault,
@@ -117,32 +98,32 @@ describe('accounts', { tags: '@smoke' }, () => {
);
});
it('sorting by total', () => {
it('sorting by available', () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = [
'1,000.00002',
'100,001.01',
'1,000.01',
'100,000.00',
'1,000.00',
'1,000.00',
'1,000.00001',
];
const marketsSortedAsc = [
'1,000.00',
'1,000.00',
'1,000.00001',
'1,000.00002',
'1,000.01',
'100,001.01',
'100,000.00',
];
const marketsSortedDesc = [
'100,001.01',
'1,000.01',
'100,000.00',
'1,000.00002',
'1,000.00001',
'1,000.00',
'1,000.00',
];
checkSorting(
'total',
'available',
marketsSortedDefault,
marketsSortedAsc,
marketsSortedDesc
@@ -50,6 +50,7 @@ describe('positions', { tags: '@smoke' }, () => {
const emptyCells = [
'notional',
'markPrice',
'liquidationPrice',
'currentLeverage',
'averageEntryPrice',
];
@@ -161,6 +162,8 @@ describe('positions', { tags: '@smoke' }, () => {
cy.wrap($prices).invoke('text').should('not.be.empty');
});
cy.get('[col-id="liquidationPrice"]').should('contain.text', '0'); // liquidation price
cy.get('[col-id="currentLeverage"]').should('contain.text', '2.846.1');
cy.get('[col-id="marginAccountBalance"]') // margin allocated
@@ -523,16 +523,6 @@ const VegaTxCompleteToastsContent = ({ tx }: VegaTxToastContentProps) => {
<div>
<h3 className="font-bold">{t('Transfer complete')}</h3>
<p>{t('Your transaction has been confirmed ')}</p>
{tx.txHash && (
<p className="break-all">
<ExternalLink
href={explorerLink(EXPLORER_TX.replace(':hash', tx.txHash))}
rel="noreferrer"
>
{t('View in block explorer')}
</ExternalLink>
</p>
)}
<VegaTransactionDetails tx={tx} />
</div>
);
+1 -1
View File
@@ -83,8 +83,8 @@ function AppBody({ Component }: AppProps) {
</Head>
<Title />
<div className={gridClasses}>
<Banner />
<Navbar theme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'system'} />
<Banner />
<ViewingBanner />
<main data-testid={location.pathname}>
<Component />
@@ -159,50 +159,38 @@ const accountResult = [
{
asset: {
__typename: 'Asset',
decimals: 5,
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
decimals: 5,
},
balance: '4000000000000001006031',
type: 'ACCOUNT_TYPE_GENERAL',
available: '4000000000000001006031',
balance: '4000000000000001006031',
breakdown: [],
deposited: '4000000000000001006031',
type: AccountType.ACCOUNT_TYPE_GENERAL,
used: '0',
total: '4000000000000001006031',
breakdown: [
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '4000000000000001006031',
market: null,
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
decimals: 5,
},
total: '4000000000000001006031',
available: '4000000000000001006031',
used: '4000000000000001006031',
},
],
},
{
asset: {
__typename: 'Asset',
decimals: 5,
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
decimals: 5,
},
balance: '5000593078',
type: 'ACCOUNT_TYPE_GENERAL',
available: '5000593078',
used: '406922',
total: '5001000000',
balance: '5000593078',
breakdown: [
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_MARGIN',
asset: {
__typename: 'Asset',
decimals: 5,
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
},
available: '5000593078',
balance: '406922',
deposited: '5001000000',
market: {
__typename: 'Market',
id: '9c1ee71959e566c484fcea796513137f8a02219cca2e973b7ae72dc29d099581',
@@ -214,50 +202,35 @@ const accountResult = [
},
},
},
asset: {
__typename: 'Asset',
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
decimals: 5,
},
total: '5001000000',
available: '5000593078',
type: AccountType.ACCOUNT_TYPE_MARGIN,
used: '406922',
},
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '5000593078',
market: null,
asset: {
__typename: 'Asset',
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
decimals: 5,
},
total: '5001000000',
available: '5000593078',
used: '5000593078',
},
],
deposited: '5001000000',
type: AccountType.ACCOUNT_TYPE_GENERAL,
used: '406922',
},
{
asset: {
__typename: 'Asset',
decimals: 5,
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
decimals: 5,
},
balance: '2996218603',
type: 'ACCOUNT_TYPE_GENERAL',
available: '2996218603',
used: '2781397',
total: '2999000000',
balance: '2996218603',
breakdown: [
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_MARGIN',
asset: {
__typename: 'Asset',
decimals: 5,
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
},
available: '2996218603',
balance: '2781397',
deposited: '2999000000',
market: {
__typename: 'Market',
id: 'd90fd7c746286625504d7a3f5f420a280875acd3cd611676d9e70acc675f4540',
@@ -269,91 +242,40 @@ const accountResult = [
},
},
},
asset: {
__typename: 'Asset',
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
decimals: 5,
},
total: '2999000000',
available: '2996218603',
type: AccountType.ACCOUNT_TYPE_MARGIN,
used: '2781397',
},
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '2996218603',
market: null,
asset: {
__typename: 'Asset',
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
decimals: 5,
},
total: '2999000000',
available: '2996218603',
used: '2996218603',
},
],
deposited: '2999000000',
type: AccountType.ACCOUNT_TYPE_GENERAL,
used: '2781397',
},
{
asset: {
__typename: 'Asset',
decimals: 5,
id: '993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede',
symbol: 'tUSDC',
decimals: 5,
},
balance: '1990351587',
type: 'ACCOUNT_TYPE_GENERAL',
available: '1990351587',
balance: '1990351587',
breakdown: [],
deposited: '1990351587',
type: AccountType.ACCOUNT_TYPE_GENERAL,
used: '0',
total: '1990351587',
breakdown: [
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '1990351587',
market: null,
asset: {
__typename: 'Asset',
id: '993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede',
symbol: 'tUSDC',
decimals: 5,
},
total: '1990351587',
available: '1990351587',
used: '1990351587',
},
],
},
{
asset: {
__typename: 'Asset',
decimals: 5,
id: 'XYZalpha',
symbol: 'XYZalpha',
decimals: 5,
},
balance: '10001000000',
type: 'ACCOUNT_TYPE_GENERAL',
available: '10001000000',
balance: '10001000000',
breakdown: [],
deposited: '10001000000',
type: AccountType.ACCOUNT_TYPE_GENERAL,
used: '0',
total: '10001000000',
breakdown: [
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '10001000000',
market: null,
asset: {
__typename: 'Asset',
id: 'XYZalpha',
symbol: 'XYZalpha',
decimals: 5,
},
total: '10001000000',
available: '10001000000',
used: '10001000000',
},
],
},
] as AccountFields[];
@@ -99,7 +99,7 @@ export const accountsOnlyDataProvider = makeDataProvider<
export interface AccountFields extends Account {
available: string;
used: string;
total: string;
deposited: string;
balance: string;
breakdown?: AccountFields[];
}
@@ -145,17 +145,15 @@ const getAssetAccountAggregation = (
type: AccountType.ACCOUNT_TYPE_GENERAL,
available: available.toString(),
used: used.toString(),
total: (available + used).toString(),
deposited: (available + used).toString(),
};
const breakdown = accounts
.filter((a) =>
[...USE_ACCOUNT_TYPES, AccountType.ACCOUNT_TYPE_GENERAL].includes(a.type)
)
.filter((a) => USE_ACCOUNT_TYPES.includes(a.type))
.map((a) => ({
...a,
asset: accounts[0].asset,
total: balanceAccount.total,
deposited: balanceAccount.deposited,
available: balanceAccount.available,
used: a.balance,
}))
+13 -7
View File
@@ -27,7 +27,7 @@ const singleRow = {
},
available: '125600000',
used: '125600000',
total: '251200000',
deposited: '125600000',
} as AccountFields;
const singleRowData = [singleRow];
@@ -42,7 +42,7 @@ describe('AccountsTable', () => {
/>
);
});
const expectedHeaders = ['Asset', 'Used', 'Available', 'Total', ''];
const expectedHeaders = ['Asset', 'Total', 'Used', 'Available', ''];
const headers = await screen.findAllByRole('columnheader');
expect(headers).toHaveLength(expectedHeaders.length);
expect(
@@ -65,7 +65,8 @@ describe('AccountsTable', () => {
'tBTC',
'1,256.00',
'1,256.00',
'2,512.00',
'1,256.00',
'Breakdown',
'Deposit',
'Withdraw',
];
@@ -87,8 +88,13 @@ describe('AccountsTable', () => {
);
});
const cells = await screen.findAllByRole('gridcell');
const expectedValues = ['tBTC', '1,256.00', '1,256.00', '2,512.00', ''];
expect(cells.length).toBe(expectedValues.length);
const expectedValues = [
'tBTC',
'1,256.00',
'1,256.00',
'1,256.00',
'Breakdown',
];
cells.forEach((cell, i) => {
expect(cell).toHaveTextContent(expectedValues[i]);
});
@@ -139,7 +145,7 @@ describe('AccountsTable', () => {
},
available: '0',
balance: '125600000',
total: '125600000',
deposited: '125600000',
market: {
__typename: 'Market',
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
@@ -155,7 +161,7 @@ describe('AccountsTable', () => {
used: '125600000',
},
],
total: '125600000',
deposited: '125600000',
type: 'ACCOUNT_TYPE_GENERAL',
used: '125600000',
},
+167 -183
View File
@@ -8,6 +8,7 @@ import { t } from '@vegaprotocol/i18n';
import type {
VegaICellRendererParams,
VegaValueFormatterParams,
VegaValueGetterParams,
} from '@vegaprotocol/datagrid';
import { Button, ButtonLink, Dialog } from '@vegaprotocol/ui-toolkit';
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
@@ -16,56 +17,12 @@ import {
CenteredGridCellWrapper,
} from '@vegaprotocol/datagrid';
import { AgGridColumn } from 'ag-grid-react';
import type { IDatasource, IGetRowsParams, RowNode } from 'ag-grid-community';
import type { IDatasource, IGetRowsParams } from 'ag-grid-community';
import type { AgGridReact, AgGridReactProps } from 'ag-grid-react';
import BreakdownTable from './breakdown-table';
import type { AccountFields } from './accounts-data-provider';
import type { Asset } from '@vegaprotocol/types';
import BigNumber from 'bignumber.js';
import classNames from 'classnames';
const colorClass = (percentageUsed: number, neutral = false) => {
return classNames({
'text-neutral-500 dark:text-neutral-400': percentageUsed < 75 && !neutral,
'text-vega-orange': percentageUsed >= 75 && percentageUsed < 90,
'text-vega-pink': percentageUsed >= 90,
});
};
export const percentageValue = (part?: string, total?: string) =>
new BigNumber(part || 0)
.dividedBy(total || 1)
.multipliedBy(100)
.toNumber();
const formatWithAssetDecimals = (
data: AccountFields | undefined,
value: string | undefined
) => {
return (
data &&
data.asset &&
isNumeric(value) &&
addDecimalsFormatNumber(value, data.asset.decimals)
);
};
export const accountValuesComparator = (
valueA: string,
valueB: string,
nodeA: RowNode,
nodeB: RowNode
) => {
if (isNumeric(valueA) && isNumeric(valueB)) {
const a = toBigNum(valueA, nodeA.data.asset?.decimals);
const b = toBigNum(valueB, nodeB.data.asset?.decimals);
if (a.isEqualTo(b)) return 0;
return a.isGreaterThan(b) ? 1 : -1;
}
if (valueA === valueB) return 0;
return valueA > valueB ? 1 : -1;
};
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
@@ -90,7 +47,7 @@ export interface AccountTableProps extends AgGridReactProps {
export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
({ onClickAsset, onClickWithdraw, onClickDeposit, ...props }, ref) => {
const [openBreakdown, setOpenBreakdown] = useState(false);
const [row, setRow] = useState<AccountFields>();
const [breakdown, setBreakdown] = useState<AccountFields[] | null>(null);
const pinnedAssetId = props.pinnedAsset?.id;
const pinnedAssetRow = useMemo(() => {
@@ -103,7 +60,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
asset: props.pinnedAsset,
available: '0',
used: '0',
total: '0',
deposited: '0',
balance: '0',
};
}
@@ -124,7 +81,6 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
resizable: true,
tooltipComponent: TooltipCellComponent,
sortable: true,
comparator: accountValuesComparator,
}}
{...props}
pinnedTopRowData={pinnedAssetRow ? [pinnedAssetRow] : undefined}
@@ -138,64 +94,90 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
cellRenderer={({
value,
data,
node,
}: VegaICellRendererParams<AccountFields, 'asset.symbol'>) => {
return (
<ButtonLink
data-testid="asset"
onClick={() => {
if (data) {
onClickAsset(data.asset.id);
}
}}
return value ? (
<CenteredGridCellWrapper
className={node.rowPinned ? 'h-[30px]' : undefined}
>
{value}
</ButtonLink>
);
<ButtonLink
data-testid="asset"
onClick={() => {
if (data) {
onClickAsset(data.asset.id);
}
}}
>
{value}
</ButtonLink>
</CenteredGridCellWrapper>
) : null;
}}
maxWidth={300}
/>
<AgGridColumn
headerName={t('Total')}
type="rightAligned"
field="deposited"
headerTooltip={t(
'This is the total amount of collateral used plus the amount available in your general account.'
)}
valueGetter={({
data,
}: VegaValueGetterParams<AccountFields, 'deposited'>) => {
return !data?.deposited
? undefined
: toBigNum(data.deposited, data.asset.decimals).toNumber();
}}
maxWidth={300}
cellRenderer={({
data,
node,
}: VegaICellRendererParams<AccountFields, 'deposited'>) => {
const valueFormatted =
data &&
data.asset &&
isNumeric(data.deposited) &&
addDecimalsFormatNumber(data.deposited, data.asset.decimals);
return node.rowPinned ? (
<CenteredGridCellWrapper className="h-[30px] justify-end">
{valueFormatted}
</CenteredGridCellWrapper>
) : (
valueFormatted
);
}}
/>
<AgGridColumn
headerName={t('Used')}
type="rightAligned"
field="used"
headerTooltip={t(
'Currently allocated to a market as margin or bond. Check the breakdown for details.'
'This is the amount of collateral used from your general account.'
)}
valueGetter={({
data,
}: VegaValueGetterParams<AccountFields, 'used'>) => {
return !data?.used
? undefined
: toBigNum(data.used, data.asset.decimals).toNumber();
}}
maxWidth={300}
cellRenderer={({
data,
value,
node,
}: VegaICellRendererParams<AccountFields, 'used'>) => {
if (!data) return null;
const percentageUsed = percentageValue(value, data.total);
const valueFormatted = formatWithAssetDecimals(data, value);
return data.breakdown ? (
<>
<ButtonLink
data-testid="breakdown"
onClick={() => {
setOpenBreakdown(!openBreakdown);
setRow(data);
}}
>
<span>{valueFormatted}</span>
</ButtonLink>
<span
className={classNames(
colorClass(percentageUsed),
'ml-2 inline-block w-14'
)}
>
{percentageUsed.toFixed(2)}%
</span>
</>
const valueFormatted =
data &&
data.asset &&
isNumeric(data.used) &&
addDecimalsFormatNumber(data.used, data.asset.decimals);
return node.rowPinned ? (
<CenteredGridCellWrapper className="h-[30px] justify-end">
{valueFormatted}
</CenteredGridCellWrapper>
) : (
<>
<span>{valueFormatted}</span>
<span className="ml-2 inline-block w-14 text-neutral-500 dark:text-neutral-400">
0.00%
</span>
</>
valueFormatted
);
}}
/>
@@ -204,113 +186,115 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
field="available"
type="rightAligned"
headerTooltip={t(
'Deposited on the network, but not allocated to a market. Free to use for placing orders or providing liquidity.'
'This is the amount of collateral available in your general account.'
)}
cellRenderer={({
value,
valueGetter={({
data,
}: VegaValueGetterParams<AccountFields, 'available'>) => {
return !data?.available
? undefined
: toBigNum(data.available, data.asset.decimals).toNumber();
}}
valueFormatter={({
data,
}: VegaValueFormatterParams<AccountFields, 'available'>) =>
data &&
data.asset &&
isNumeric(data.available) &&
addDecimalsFormatNumber(data.available, data.asset.decimals)
}
maxWidth={300}
cellRenderer={({
data,
node,
}: VegaICellRendererParams<AccountFields, 'available'>) => {
const percentageUsed = percentageValue(data?.used, data?.total);
return (
<span className={colorClass(percentageUsed, true)}>
{formatWithAssetDecimals(data, value)}
</span>
const valueFormatted =
data &&
data.asset &&
isNumeric(data.available) &&
addDecimalsFormatNumber(data.available, data.asset.decimals);
return node.rowPinned ? (
<CenteredGridCellWrapper className="h-[30px] justify-end">
{valueFormatted}
</CenteredGridCellWrapper>
) : (
valueFormatted
);
}}
/>
<AgGridColumn
headerName={t('Total')}
colId="breakdown"
headerName=""
sortable={false}
minWidth={200}
type="rightAligned"
field="total"
headerTooltip={t(
'The total amount of each asset on this key. Includes used and available collateral.'
)}
valueFormatter={({
cellRenderer={({
data,
}: VegaValueFormatterParams<AccountFields, 'total'>) =>
formatWithAssetDecimals(data, data?.total)
}
/>
{
<AgGridColumn
colId="accounts-actions"
headerName=""
sortable={false}
minWidth={200}
type="rightAligned"
cellRenderer={({
data,
}: VegaICellRendererParams<AccountFields>) => {
if (!data) return null;
else {
if (
data.asset.id === pinnedAssetId &&
new BigNumber(data.total).isLessThanOrEqualTo(0)
) {
return (
<CenteredGridCellWrapper className="h-[30px] justify-end py-1">
<Button
size="xs"
variant="primary"
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit to trade')}
</Button>
</CenteredGridCellWrapper>
);
}
}: VegaICellRendererParams<AccountFields>) => {
if (!data) return null;
else {
if (
data.asset.id === pinnedAssetId &&
new BigNumber(data.deposited).isLessThanOrEqualTo(0)
) {
return (
<>
<span className="mx-1" />
{!props.isReadOnly && (
<ButtonLink
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit')}
</ButtonLink>
)}
<span className="mx-1" />
{!props.isReadOnly && (
<ButtonLink
data-testid="withdraw"
onClick={() =>
onClickWithdraw && onClickWithdraw(data.asset.id)
}
>
{t('Withdraw')}
</ButtonLink>
)}
</>
<CenteredGridCellWrapper className="h-[30px] justify-end py-1">
<Button
size="xs"
variant="primary"
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit to trade')}
</Button>
</CenteredGridCellWrapper>
);
}
}}
/>
}
return (
<>
<ButtonLink
data-testid="breakdown"
onClick={() => {
setOpenBreakdown(!openBreakdown);
setBreakdown(data.breakdown || null);
}}
>
{t('Breakdown')}
</ButtonLink>
<span className="mx-1" />
{!props.isReadOnly && (
<ButtonLink
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit')}
</ButtonLink>
)}
<span className="mx-1" />
{!props.isReadOnly && (
<ButtonLink
data-testid="withdraw"
onClick={() =>
onClickWithdraw && onClickWithdraw(data.asset.id)
}
>
{t('Withdraw')}
</ButtonLink>
)}
</>
);
}
}}
/>
</AgGrid>
<Dialog size="medium" open={openBreakdown} onChange={setOpenBreakdown}>
<div className="h-[35vh] w-full m-auto flex flex-col">
<h1 className="text-xl mb-4">
{row?.asset?.symbol} {t('usage breakdown')}
</h1>
{row && (
<p className="mb-2 text-sm">
{t('You have %s %s in total.', [
addDecimalsFormatNumber(row.total, row.asset.decimals),
row.asset.symbol,
])}
</p>
)}
<BreakdownTable
data={row?.breakdown || null}
domLayout="autoHeight"
/>
<h1 className="text-xl mb-4">{t('Collateral breakdown')}</h1>
<BreakdownTable data={breakdown} domLayout="autoHeight" />
</div>
</Dialog>
</>
@@ -27,7 +27,7 @@ const singleRow = {
},
available: '125600000',
used: '125600000',
total: '251200000',
deposited: '125600000',
} as AccountFields;
const singleRowData = [singleRow];
@@ -37,10 +37,10 @@ describe('BreakdownTable', () => {
render(<BreakdownTable data={singleRowData} />);
});
const headers = await screen.findAllByRole('columnheader');
expect(headers).toHaveLength(3);
expect(headers).toHaveLength(4);
expect(
headers.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim())
).toEqual(['Market', 'Account type', 'Balance']);
).toEqual(['Account type', 'Market', 'Used', 'Balance']);
});
it('should apply correct formatting', async () => {
@@ -49,9 +49,9 @@ describe('BreakdownTable', () => {
});
const cells = await screen.findAllByRole('gridcell');
const expectedValues = [
'BTCUSD Monthly (30 Jun 2022)',
'Margin',
'1,256.00 (50%)',
'BTCUSD Monthly (30 Jun 2022)',
'1,256.001,256.00',
'1,256.00',
'1,256.00',
];
@@ -83,7 +83,7 @@ describe('BreakdownTable', () => {
},
available: '0',
balance: '125600000',
total: '125600000',
deposited: '125600000',
market: {
__typename: 'Market',
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
@@ -99,7 +99,7 @@ describe('BreakdownTable', () => {
used: '125600000',
},
],
total: '125600000',
deposited: '125600000',
type: 'ACCOUNT_TYPE_GENERAL',
used: '125600000',
},
+42 -23
View File
@@ -1,5 +1,5 @@
import { forwardRef } from 'react';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import {
Intent,
@@ -13,7 +13,6 @@ import type { ValueProps } from '@vegaprotocol/ui-toolkit';
import type { VegaValueFormatterParams } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid, PriceCell } from '@vegaprotocol/datagrid';
import type { ValueFormatterParams } from 'ag-grid-community';
import { accountValuesComparator } from './accounts-table';
export const progressBarValueFormatter = ({
data,
@@ -24,16 +23,24 @@ export const progressBarValueFormatter = ({
}
const min = BigInt(data.used);
const mid = BigInt(data.available);
const max = BigInt(data.total);
const max = BigInt(data.deposited);
const range = max > min ? max : min;
return {
low: addDecimalsFormatNumber(min.toString(), data.asset.decimals),
high: addDecimalsFormatNumber(mid.toString(), data.asset.decimals),
low: addDecimalsFormatNumber(min.toString(), data.asset.decimals, 4),
high: addDecimalsFormatNumber(mid.toString(), data.asset.decimals, 4),
value: range ? Number((min * BigInt(100)) / range) : 0,
intent: Intent.Warning,
};
};
export const progressBarHeaderComponentParams = {
template:
'<div class="ag-cell-label-container" role="presentation">' +
` <span>${t('Available')}</span>` +
' <span ref="eText" class="ag-header-cell-text"></span>' +
'</div>',
};
interface BreakdownTableProps extends AgGridReactProps {
data: AccountFields[] | null;
}
@@ -55,23 +62,8 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
defaultColDef={{
flex: 1,
resizable: true,
sortable: true,
}}
>
<AgGridColumn
headerName={t('Market')}
field="market.tradableInstrument.instrument.name"
valueFormatter={({
value,
}: VegaValueFormatterParams<
AccountFields,
'market.tradableInstrument.instrument.name'
>) => {
if (!value) return 'None';
return value;
}}
minWidth={200}
/>
<AgGridColumn
headerName={t('Account type')}
field="type"
@@ -84,15 +76,42 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
: ''
}
/>
<AgGridColumn
headerName={t('Balance')}
headerName={t('Market')}
field="market.tradableInstrument.instrument.name"
valueFormatter={({
value,
}: VegaValueFormatterParams<
AccountFields,
'market.tradableInstrument.instrument.name'
>) => {
if (!value) return '-';
return value;
}}
minWidth={200}
/>
<AgGridColumn
headerName={t('Used')}
field="used"
flex={2}
maxWidth={500}
headerComponentParams={progressBarHeaderComponentParams}
cellRendererSelector={progressBarCellRendererSelector}
valueFormatter={progressBarValueFormatter}
comparator={accountValuesComparator}
/>
<AgGridColumn
headerName={t('Balance')}
field="balance"
valueFormatter={({
value,
data,
}: VegaValueFormatterParams<AccountFields, 'balance'>) => {
if (data && data.asset && isNumeric(value)) {
return addDecimalsFormatNumber(value, data.asset.decimals);
}
return '-';
}}
maxWidth={300}
/>
</AgGrid>
);
-1
View File
@@ -53,7 +53,6 @@ export const checkSorting = (
});
checkSortChange(orderTabDesc, column);
};
const checkSortChange = (tabsArr: string[], column: string) => {
cy.get('.ag-center-cols-container').within(() => {
tabsArr.forEach((entry, i) => {
@@ -116,7 +116,7 @@ export const DealTicket = ({
return;
}
const hasNoBalance = !BigInt(generalAccountBalance);
const hasNoBalance = generalAccountBalance === '0';
if (hasNoBalance) {
setError('summary', {
message: SummaryValidationType.NoCollateral,
@@ -141,6 +141,7 @@ export const DealTicket = ({
pubKey,
setError,
clearErrors,
errors.summary,
]);
const onSubmit = useCallback(
@@ -385,12 +386,8 @@ const SummaryMessage = memo(
// If there is no blocking error but user doesn't have enough
// balance render the margin warning, but still allow submission
if (BigInt(balance) < BigInt(margin) && BigInt(balance) > BigInt(0)) {
return (
<div className="mb-2">
<MarginWarning balance={balance} margin={margin} asset={asset} />
</div>
);
if (BigInt(balance) < BigInt(margin)) {
return <MarginWarning balance={balance} margin={margin} asset={asset} />;
}
// Show auction mode warning
if (
+18 -7
View File
@@ -134,10 +134,6 @@ export const LedgerTable = forwardRef<AgGridReact, LedgerEntryProps>(
headerName={t('Transfer type')}
field="transferType"
tooltipField="transferType"
filter={SetFilter}
filterParams={{
set: TransferTypeMapping,
}}
valueFormatter={({
value,
}: VegaValueFormatterParams<LedgerEntry, 'transferType'>) =>
@@ -151,9 +147,14 @@ export const LedgerTable = forwardRef<AgGridReact, LedgerEntryProps>(
value,
data,
}: VegaValueFormatterParams<LedgerEntry, 'quantity'>) => {
const marketDecimalPlaces = data?.marketSender?.decimalPlaces;
const assetDecimalPlaces = data?.asset?.decimals || 0;
return value
? addDecimalsFormatNumber(value, assetDecimalPlaces)
? addDecimalsFormatNumber(
value,
assetDecimalPlaces,
marketDecimalPlaces
)
: value;
}}
/>
@@ -174,9 +175,14 @@ export const LedgerTable = forwardRef<AgGridReact, LedgerEntryProps>(
value,
data,
}: VegaValueFormatterParams<LedgerEntry, 'fromAccountBalance'>) => {
const marketDecimalPlaces = data?.marketSender?.decimalPlaces;
const assetDecimalPlaces = data?.asset?.decimals || 0;
return value
? addDecimalsFormatNumber(value, assetDecimalPlaces)
? addDecimalsFormatNumber(
value,
assetDecimalPlaces,
marketDecimalPlaces
)
: value;
}}
/>
@@ -187,9 +193,14 @@ export const LedgerTable = forwardRef<AgGridReact, LedgerEntryProps>(
value,
data,
}: VegaValueFormatterParams<LedgerEntry, 'toAccountBalance'>) => {
const marketDecimalPlaces = data?.marketReceiver?.decimalPlaces;
const assetDecimalPlaces = data?.asset?.decimals || 0;
return value
? addDecimalsFormatNumber(value, assetDecimalPlaces)
? addDecimalsFormatNumber(
value,
assetDecimalPlaces,
marketDecimalPlaces
)
: value;
}}
/>
@@ -322,8 +322,9 @@ export const Info = ({ market, onSelect }: InfoProps) => {
data={{
highestPrice: bounds.maxValidPrice,
lowestPrice: bounds.minValidPrice,
referencePrice: bounds.referencePrice,
}}
decimalPlaces={market.decimalPlaces}
decimalPlaces={assetDecimals}
assetSymbol={quoteUnit}
/>
)}
@@ -213,6 +213,7 @@ describe('getMetrics && rejoinPositionData', () => {
expect(metrics[0].marketDecimalPlaces).toEqual(5);
expect(metrics[0].positionDecimalPlaces).toEqual(0);
expect(metrics[0].decimals).toEqual(5);
expect(metrics[0].liquidationPrice).toEqual('169990');
expect(metrics[0].lowMarginLevel).toEqual(false);
expect(metrics[0].markPrice).toEqual('9431775');
expect(metrics[0].marketId).toEqual(
@@ -241,6 +242,7 @@ describe('getMetrics && rejoinPositionData', () => {
expect(metrics[1].marketDecimalPlaces).toEqual(5);
expect(metrics[1].positionDecimalPlaces).toEqual(0);
expect(metrics[1].decimals).toEqual(5);
expect(metrics[1].liquidationPrice).toEqual('9830750');
expect(metrics[1].lowMarginLevel).toEqual(false);
expect(metrics[1].markPrice).toEqual('869762');
expect(metrics[1].marketId).toEqual(
@@ -67,6 +67,7 @@ export interface Position {
positionDecimalPlaces: number;
totalBalance: string;
assetSymbol: string;
liquidationPrice: string | undefined;
lowMarginLevel: boolean;
marketId: string;
marketTradingMode: Schema.MarketTradingMode;
@@ -139,6 +140,7 @@ export const getMetrics = (
? new BigNumber(0)
: marginAccountBalance.dividedBy(totalBalance).multipliedBy(100);
const marginMaintenance = toBigNum(marginLevel.maintenanceLevel, decimals);
const marginSearch = toBigNum(marginLevel.searchLevel, decimals);
const marginInitial = toBigNum(marginLevel.initialLevel, decimals);
@@ -149,6 +151,17 @@ export const getMetrics = (
.plus(markPrice)
: undefined;
const liquidationPrice = markPrice
? BigNumber.maximum(
0,
marginMaintenance
.minus(marginAccountBalance)
.minus(generalAccountBalance)
.dividedBy(openVolume)
.plus(markPrice)
)
: undefined;
const lowMarginLevel =
marginAccountBalance.isLessThan(
marginSearch.plus(marginInitial.minus(marginSearch).dividedBy(2))
@@ -167,6 +180,9 @@ export const getMetrics = (
market.tradableInstrument.instrument.product.settlementAsset.symbol,
totalBalance: totalBalance.multipliedBy(10 ** decimals).toFixed(),
lowMarginLevel,
liquidationPrice: liquidationPrice
? liquidationPrice.multipliedBy(10 ** marketDecimalPlaces).toFixed(0)
: undefined,
marketId: market.id,
marketTradingMode: market.tradingMode,
markPrice: marketData ? marketData.markPrice : undefined,
@@ -17,6 +17,7 @@ const singleRow: Position = {
decimals: 2,
totalBalance: '123456',
assetSymbol: 'BTC',
liquidationPrice: '83',
lowMarginLevel: false,
marketId: 'string',
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
@@ -49,7 +50,7 @@ it('render correct columns', async () => {
});
const headers = screen.getAllByRole('columnheader');
expect(headers).toHaveLength(11);
expect(headers).toHaveLength(12);
expect(
headers.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim())
).toEqual([
@@ -59,6 +60,7 @@ it('render correct columns', async () => {
'Mark price',
'Settlement asset',
'Entry price',
'Liquidation price (est)',
'Leverage',
'Margin allocated',
'Realised PNL',
@@ -144,12 +146,33 @@ it('displays mark price', async () => {
expect(cells[3].textContent).toEqual('-');
});
it("displays properly entry, liquidation price and liquidation bar and it's intent", async () => {
let result: RenderResult;
await act(async () => {
result = render(
<PositionsTable rowData={singleRowData} isReadOnly={false} />
);
});
let cells = screen.getAllByRole('gridcell');
const entryPrice = cells[5].firstElementChild?.firstElementChild?.textContent;
expect(entryPrice).toEqual('13.3');
await act(async () => {
result.rerender(
<PositionsTable
rowData={[{ ...singleRow, lowMarginLevel: true }]}
isReadOnly={false}
/>
);
});
cells = screen.getAllByRole('gridcell');
});
it('displays leverage', async () => {
await act(async () => {
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
});
const cells = screen.getAllByRole('gridcell');
expect(cells[6].textContent).toEqual('1.1');
expect(cells[7].textContent).toEqual('1.1');
});
it('displays allocated margin', async () => {
@@ -157,7 +180,7 @@ it('displays allocated margin', async () => {
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
});
const cells = screen.getAllByRole('gridcell');
const cell = cells[7];
const cell = cells[8];
expect(cell.textContent).toEqual('123,456.00');
});
@@ -166,7 +189,8 @@ it('displays realised and unrealised PNL', async () => {
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
});
const cells = screen.getAllByRole('gridcell');
expect(cells[9].textContent).toEqual('4.56');
expect(cells[9].textContent).toEqual('1.23');
expect(cells[10].textContent).toEqual('4.56');
});
it('displays close button', async () => {
@@ -182,7 +206,7 @@ it('displays close button', async () => {
);
});
const cells = screen.getAllByRole('gridcell');
expect(cells[11].textContent).toEqual('Close');
expect(cells[12].textContent).toEqual('Close');
});
it('do not display close button if openVolume is zero', async () => {
@@ -198,7 +222,7 @@ it('do not display close button if openVolume is zero', async () => {
);
});
const cells = screen.getAllByRole('gridcell');
expect(cells[11].textContent).toEqual('');
expect(cells[12].textContent).toEqual('');
});
describe('PNLCell', () => {
@@ -9,9 +9,7 @@ export default {
title: 'PositionsTable',
} as Meta;
const Template: Story = (args) => (
<PositionsTable {...args} isReadOnly={false} />
);
const Template: Story = (args) => <PositionsTable {...args} />;
export const Primary = Template.bind({});
const longPosition: Position = {
@@ -29,6 +27,7 @@ const longPosition: Position = {
// leverageMaintenance: '0',
// leverageRelease: '0',
// leverageSearch: '0',
liquidationPrice: '1129935',
lowMarginLevel: false,
marginAccountBalance: new BigNumber('0').toString(),
// marginMaintenance: '0',
@@ -43,8 +42,6 @@ const longPosition: Position = {
unrealisedPNL: '45',
searchPrice: '1132123',
updatedAt: '2022-07-27T15:02:58.400Z',
lossSocializationAmount: '0',
status: Schema.PositionStatus.POSITION_STATUS_UNSPECIFIED,
};
const shortPosition: Position = {
@@ -62,6 +59,7 @@ const shortPosition: Position = {
// leverageMaintenance: '0',
// leverageRelease: '0',
// leverageSearch: '0',
liquidationPrice: '23734',
lowMarginLevel: false,
marginAccountBalance: new BigNumber('0').toString(),
// marginMaintenance: '0',
@@ -76,8 +74,6 @@ const shortPosition: Position = {
unrealisedPNL: '0',
searchPrice: '0',
updatedAt: '2022-07-26T14:01:34.800Z',
lossSocializationAmount: '0',
status: Schema.PositionStatus.POSITION_STATUS_UNSPECIFIED,
};
Primary.args = {
@@ -249,6 +249,40 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
);
}}
/>
<AgGridColumn
headerName={t('Liquidation price (est)')}
field="liquidationPrice"
type="rightAligned"
cellRendererSelector={(): CellRendererSelectorResult => {
return {
component: PriceFlashCell,
};
}}
filter="agNumberColumnFilter"
valueGetter={({
data,
}: VegaValueGetterParams<Position, 'liquidationPrice'>) => {
return data?.liquidationPrice === undefined || !data
? undefined
: toBigNum(
data.liquidationPrice,
data.marketDecimalPlaces
).toNumber();
}}
valueFormatter={({
data,
}: VegaValueFormatterParams<Position, 'liquidationPrice'>):
| string
| undefined => {
if (!data || data?.liquidationPrice === undefined) {
return undefined;
}
return addDecimalsFormatNumber(
data.liquidationPrice,
data.marketDecimalPlaces
);
}}
/>
<AgGridColumn
headerName={t('Leverage')}
field="currentLeverage"
File diff suppressed because one or more lines are too long
+189 -69
View File
@@ -4,60 +4,134 @@ import { gql } from '@apollo/client';
import { UpdateNetworkParameterFielsFragmentDoc } from '../../proposals-data-provider/__generated__/Proposals';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ProposalEventFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null };
export type ProposalEventFieldsFragment = {
__typename?: 'Proposal';
id?: string | null;
reference: string;
state: Types.ProposalState;
rejectionReason?: Types.ProposalRejectionReason | null;
errorDetails?: string | null;
};
export type ProposalEventSubscriptionVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type ProposalEventSubscription = {
__typename?: 'Subscription';
proposals: {
__typename?: 'Proposal';
id?: string | null;
reference: string;
state: Types.ProposalState;
rejectionReason?: Types.ProposalRejectionReason | null;
errorDetails?: string | null;
};
};
export type ProposalEventSubscription = { __typename?: 'Subscription', proposals: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null } };
export type UpdateNetworkParameterProposalFragment = {
__typename?: 'Proposal';
id?: string | null;
state: Types.ProposalState;
datetime: any;
terms: {
__typename?: 'ProposalTerms';
enactmentDatetime?: any | null;
change:
| { __typename?: 'NewAsset' }
| { __typename?: 'NewFreeform' }
| { __typename?: 'NewMarket' }
| { __typename?: 'UpdateAsset' }
| { __typename?: 'UpdateMarket' }
| {
__typename?: 'UpdateNetworkParameter';
networkParameter: {
__typename?: 'NetworkParameter';
key: string;
value: string;
};
};
};
};
export type UpdateNetworkParameterProposalFragment = { __typename?: 'Proposal', id?: string | null, state: Types.ProposalState, datetime: any, terms: { __typename?: 'ProposalTerms', enactmentDatetime?: any | null, change: { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } } };
export type OnUpdateNetworkParametersSubscriptionVariables = Types.Exact<{
[key: string]: never;
}>;
export type OnUpdateNetworkParametersSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
export type OnUpdateNetworkParametersSubscription = { __typename?: 'Subscription', proposals: { __typename?: 'Proposal', id?: string | null, state: Types.ProposalState, datetime: any, terms: { __typename?: 'ProposalTerms', enactmentDatetime?: any | null, change: { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } } } };
export type OnUpdateNetworkParametersSubscription = {
__typename?: 'Subscription';
proposals: {
__typename?: 'Proposal';
id?: string | null;
state: Types.ProposalState;
datetime: any;
terms: {
__typename?: 'ProposalTerms';
enactmentDatetime?: any | null;
change:
| { __typename?: 'NewAsset' }
| { __typename?: 'NewFreeform' }
| { __typename?: 'NewMarket' }
| { __typename?: 'UpdateAsset' }
| { __typename?: 'UpdateMarket' }
| {
__typename?: 'UpdateNetworkParameter';
networkParameter: {
__typename?: 'NetworkParameter';
key: string;
value: string;
};
};
};
};
};
export type ProposalOfMarketQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
export type ProposalOfMarketQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, terms: { __typename?: 'ProposalTerms', enactmentDatetime?: any | null } } | null };
export type ProposalOfMarketQuery = {
__typename?: 'Query';
proposal?: {
__typename?: 'Proposal';
id?: string | null;
terms: { __typename?: 'ProposalTerms'; enactmentDatetime?: any | null };
} | null;
};
export const ProposalEventFieldsFragmentDoc = gql`
fragment ProposalEventFields on Proposal {
id
reference
state
rejectionReason
errorDetails
}
`;
fragment ProposalEventFields on Proposal {
id
reference
state
rejectionReason
errorDetails
}
`;
export const UpdateNetworkParameterProposalFragmentDoc = gql`
fragment UpdateNetworkParameterProposal on Proposal {
id
state
datetime
terms {
enactmentDatetime
change {
... on UpdateNetworkParameter {
...UpdateNetworkParameterFiels
fragment UpdateNetworkParameterProposal on Proposal {
id
state
datetime
terms {
enactmentDatetime
change {
... on UpdateNetworkParameter {
...UpdateNetworkParameterFiels
}
}
}
}
}
${UpdateNetworkParameterFielsFragmentDoc}`;
${UpdateNetworkParameterFielsFragmentDoc}
`;
export const ProposalEventDocument = gql`
subscription ProposalEvent($partyId: ID!) {
proposals(partyId: $partyId) {
...ProposalEventFields
subscription ProposalEvent($partyId: ID!) {
proposals(partyId: $partyId) {
...ProposalEventFields
}
}
}
${ProposalEventFieldsFragmentDoc}`;
${ProposalEventFieldsFragmentDoc}
`;
/**
* __useProposalEventSubscription__
@@ -75,19 +149,31 @@ export const ProposalEventDocument = gql`
* },
* });
*/
export function useProposalEventSubscription(baseOptions: Apollo.SubscriptionHookOptions<ProposalEventSubscription, ProposalEventSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<ProposalEventSubscription, ProposalEventSubscriptionVariables>(ProposalEventDocument, options);
}
export type ProposalEventSubscriptionHookResult = ReturnType<typeof useProposalEventSubscription>;
export type ProposalEventSubscriptionResult = Apollo.SubscriptionResult<ProposalEventSubscription>;
export const OnUpdateNetworkParametersDocument = gql`
subscription OnUpdateNetworkParameters {
proposals {
...UpdateNetworkParameterProposal
}
export function useProposalEventSubscription(
baseOptions: Apollo.SubscriptionHookOptions<
ProposalEventSubscription,
ProposalEventSubscriptionVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSubscription<
ProposalEventSubscription,
ProposalEventSubscriptionVariables
>(ProposalEventDocument, options);
}
${UpdateNetworkParameterProposalFragmentDoc}`;
export type ProposalEventSubscriptionHookResult = ReturnType<
typeof useProposalEventSubscription
>;
export type ProposalEventSubscriptionResult =
Apollo.SubscriptionResult<ProposalEventSubscription>;
export const OnUpdateNetworkParametersDocument = gql`
subscription OnUpdateNetworkParameters {
proposals {
...UpdateNetworkParameterProposal
}
}
${UpdateNetworkParameterProposalFragmentDoc}
`;
/**
* __useOnUpdateNetworkParametersSubscription__
@@ -104,22 +190,33 @@ export const OnUpdateNetworkParametersDocument = gql`
* },
* });
*/
export function useOnUpdateNetworkParametersSubscription(baseOptions?: Apollo.SubscriptionHookOptions<OnUpdateNetworkParametersSubscription, OnUpdateNetworkParametersSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<OnUpdateNetworkParametersSubscription, OnUpdateNetworkParametersSubscriptionVariables>(OnUpdateNetworkParametersDocument, options);
}
export type OnUpdateNetworkParametersSubscriptionHookResult = ReturnType<typeof useOnUpdateNetworkParametersSubscription>;
export type OnUpdateNetworkParametersSubscriptionResult = Apollo.SubscriptionResult<OnUpdateNetworkParametersSubscription>;
export function useOnUpdateNetworkParametersSubscription(
baseOptions?: Apollo.SubscriptionHookOptions<
OnUpdateNetworkParametersSubscription,
OnUpdateNetworkParametersSubscriptionVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSubscription<
OnUpdateNetworkParametersSubscription,
OnUpdateNetworkParametersSubscriptionVariables
>(OnUpdateNetworkParametersDocument, options);
}
export type OnUpdateNetworkParametersSubscriptionHookResult = ReturnType<
typeof useOnUpdateNetworkParametersSubscription
>;
export type OnUpdateNetworkParametersSubscriptionResult =
Apollo.SubscriptionResult<OnUpdateNetworkParametersSubscription>;
export const ProposalOfMarketDocument = gql`
query ProposalOfMarket($marketId: ID!) {
proposal(id: $marketId) {
id
terms {
enactmentDatetime
query ProposalOfMarket($marketId: ID!) {
proposal(id: $marketId) {
id
terms {
enactmentDatetime
}
}
}
}
`;
`;
/**
* __useProposalOfMarketQuery__
@@ -137,14 +234,37 @@ export const ProposalOfMarketDocument = gql`
* },
* });
*/
export function useProposalOfMarketQuery(baseOptions: Apollo.QueryHookOptions<ProposalOfMarketQuery, ProposalOfMarketQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ProposalOfMarketQuery, ProposalOfMarketQueryVariables>(ProposalOfMarketDocument, options);
}
export function useProposalOfMarketLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ProposalOfMarketQuery, ProposalOfMarketQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ProposalOfMarketQuery, ProposalOfMarketQueryVariables>(ProposalOfMarketDocument, options);
}
export type ProposalOfMarketQueryHookResult = ReturnType<typeof useProposalOfMarketQuery>;
export type ProposalOfMarketLazyQueryHookResult = ReturnType<typeof useProposalOfMarketLazyQuery>;
export type ProposalOfMarketQueryResult = Apollo.QueryResult<ProposalOfMarketQuery, ProposalOfMarketQueryVariables>;
export function useProposalOfMarketQuery(
baseOptions: Apollo.QueryHookOptions<
ProposalOfMarketQuery,
ProposalOfMarketQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<ProposalOfMarketQuery, ProposalOfMarketQueryVariables>(
ProposalOfMarketDocument,
options
);
}
export function useProposalOfMarketLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
ProposalOfMarketQuery,
ProposalOfMarketQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
ProposalOfMarketQuery,
ProposalOfMarketQueryVariables
>(ProposalOfMarketDocument, options);
}
export type ProposalOfMarketQueryHookResult = ReturnType<
typeof useProposalOfMarketQuery
>;
export type ProposalOfMarketLazyQueryHookResult = ReturnType<
typeof useProposalOfMarketLazyQuery
>;
export type ProposalOfMarketQueryResult = Apollo.QueryResult<
ProposalOfMarketQuery,
ProposalOfMarketQueryVariables
>;
@@ -3,31 +3,42 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type VoteEventFieldsFragment = { __typename?: 'ProposalVote', proposalId: string, vote: { __typename?: 'Vote', value: Types.VoteValue, datetime: any } };
export type VoteEventFieldsFragment = {
__typename?: 'ProposalVote';
proposalId: string;
vote: { __typename?: 'Vote'; value: Types.VoteValue; datetime: any };
};
export type VoteEventSubscriptionVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type VoteEventSubscription = { __typename?: 'Subscription', votes: { __typename?: 'ProposalVote', proposalId: string, vote: { __typename?: 'Vote', value: Types.VoteValue, datetime: any } } };
export type VoteEventSubscription = {
__typename?: 'Subscription';
votes: {
__typename?: 'ProposalVote';
proposalId: string;
vote: { __typename?: 'Vote'; value: Types.VoteValue; datetime: any };
};
};
export const VoteEventFieldsFragmentDoc = gql`
fragment VoteEventFields on ProposalVote {
proposalId
vote {
value
datetime
fragment VoteEventFields on ProposalVote {
proposalId
vote {
value
datetime
}
}
}
`;
`;
export const VoteEventDocument = gql`
subscription VoteEvent($partyId: ID!) {
votes(partyId: $partyId) {
...VoteEventFields
subscription VoteEvent($partyId: ID!) {
votes(partyId: $partyId) {
...VoteEventFields
}
}
}
${VoteEventFieldsFragmentDoc}`;
${VoteEventFieldsFragmentDoc}
`;
/**
* __useVoteEventSubscription__
@@ -45,9 +56,20 @@ export const VoteEventDocument = gql`
* },
* });
*/
export function useVoteEventSubscription(baseOptions: Apollo.SubscriptionHookOptions<VoteEventSubscription, VoteEventSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<VoteEventSubscription, VoteEventSubscriptionVariables>(VoteEventDocument, options);
}
export type VoteEventSubscriptionHookResult = ReturnType<typeof useVoteEventSubscription>;
export type VoteEventSubscriptionResult = Apollo.SubscriptionResult<VoteEventSubscription>;
export function useVoteEventSubscription(
baseOptions: Apollo.SubscriptionHookOptions<
VoteEventSubscription,
VoteEventSubscriptionVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSubscription<
VoteEventSubscription,
VoteEventSubscriptionVariables
>(VoteEventDocument, options);
}
export type VoteEventSubscriptionHookResult = ReturnType<
typeof useVoteEventSubscription
>;
export type VoteEventSubscriptionResult =
Apollo.SubscriptionResult<VoteEventSubscription>;
-4
View File
@@ -1098,8 +1098,6 @@ export type InternalDataSourceKind = DataSourceSpecConfigurationTime;
/** The interval for trade candles when subscribing via Vega GraphQL, default is I15M */
export enum Interval {
/** The block interval is not a fixed amount of time, rather it used to indicate grouping of events that occur in a single block. It is usually about a second. */
INTERVAL_BLOCK = 'INTERVAL_BLOCK',
/** 1 day interval */
INTERVAL_I1D = 'INTERVAL_I1D',
/** 1 hour interval */
@@ -3807,8 +3805,6 @@ export type StakeLinking = {
__typename?: 'StakeLinking';
/** The amount linked or unlinked */
amount: Scalars['String'];
/** The (ethereum) block height of the link/unlink */
blockHeight: Scalars['String'];
/** The time at which the stake linking was fully processed by the Vega network, null until defined */
finalizedAt?: Maybe<Scalars['Timestamp']>;
id: Scalars['ID'];
-1
View File
@@ -86,7 +86,6 @@ export const DepositStatusMapping: {
export const IntervalMapping: {
[T in Interval]: string;
} = {
INTERVAL_BLOCK: '1 block',
INTERVAL_I15M: 'I15M',
INTERVAL_I1D: 'I1D',
INTERVAL_I1H: 'I1H',
@@ -20,9 +20,8 @@ export const ProgressBarCell = ({ valueFormatted }: ValueProps) => {
return valueFormatted ? (
<>
<div className="flex justify-between leading-tight font-mono">
<div>
{valueFormatted.low} ({valueFormatted.value}%)
</div>
<div>{valueFormatted.low}</div>
<div>{valueFormatted.high}</div>
</div>
<ProgressBar
value={valueFormatted.value}