Compare commits
38
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c81c5f895 | ||
|
|
898d3a329f | ||
|
|
90b38478ae | ||
|
|
f1b8d613bf | ||
|
|
e3c8e0359f | ||
|
|
96fcd285f5 | ||
|
|
e82e4f91ac | ||
|
|
127467bdd0 | ||
|
|
0e87d7acbc | ||
|
|
45ae5cd781 | ||
|
|
f837ed37f2 | ||
|
|
904bdc11a9 | ||
|
|
594eb0aa28 | ||
|
|
284756decc | ||
|
|
3b88fd6926 | ||
|
|
99f16e9882 | ||
|
|
c27edced16 | ||
|
|
d91b100d42 | ||
|
|
906fc2a241 | ||
|
|
92d6999c1f | ||
|
|
43f46aa94a | ||
|
|
2c5cc66706 | ||
|
|
9fa2ee6351 | ||
|
|
1c3dd1daf6 | ||
|
|
bb2f7fa33c | ||
|
|
5433b7ee01 | ||
|
|
49117bf9d5 | ||
|
|
871c6907ac | ||
|
|
eca2005c44 | ||
|
|
fd5454faf5 | ||
|
|
c9feb63b9a | ||
|
|
33f50ea8dc | ||
|
|
d52577f2e6 | ||
|
|
22dc12149b | ||
|
|
9442fe2012 | ||
|
|
8c19d99b6b | ||
|
|
0d9c0e396c | ||
|
|
9f88c7e031 |
@@ -40,12 +40,10 @@ jobs:
|
||||
- name: See affected apps
|
||||
run: |
|
||||
affected=$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)
|
||||
echo -n "Affected projects: $affected"
|
||||
projects=""
|
||||
if [[ $affected == *"token"* ]]; then projects+='"token-e2e" '; fi
|
||||
if [[ $affected == *"trading"* ]]; then projects+='"trading-e2e" '; fi
|
||||
if [[ $affected == *"explorer"* ]]; then projects+='"explorer-e2e" '; fi
|
||||
if [[ -z "$projects" ]]; then projects+='"token-e2e" "trading-e2e" "explorer-e2e" '; fi
|
||||
projects=${projects%?}
|
||||
projects=[${projects// /,}]
|
||||
echo PROJECTS=$projects >> $GITHUB_ENV
|
||||
|
||||
@@ -68,6 +68,7 @@ jobs:
|
||||
working-directory: frontend-monorepo
|
||||
env:
|
||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
|
||||
CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }}
|
||||
CYPRESS_grepTags: ${{ inputs.tags }}
|
||||
|
||||
|
||||
@@ -6,5 +6,4 @@ NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https:
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://dev.token.vega.xyz
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
@@ -7,4 +7,3 @@ NX_VEGA_ENV=MAINNET
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest/
|
||||
NX_ETHERSCAN_URL=https://etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://token.vega.xyz
|
||||
|
||||
@@ -7,7 +7,6 @@ NX_VEGA_ENV=MIRROR
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=https://be.mainnet-mirror.vega.xyz/rest/
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://mainnet-mirror.token.vega.xyz
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -9,4 +9,3 @@ NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https:
|
||||
NX_TENDERMINT_URL=https://tm.n01.sandbox.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.sandbox.vega.xyz/websocket
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://sandbox.token.vega.xyz
|
||||
|
||||
@@ -11,4 +11,3 @@ NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://stagnet1.token.vega.xyz
|
||||
|
||||
@@ -4,5 +4,4 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
|
||||
NX_VEGA_GOVERNANCE_URL=https://stagnet3.token.vega.xyz
|
||||
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
|
||||
@@ -10,4 +10,3 @@ NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_VEGA_NETWORKS={}
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://token.fairground.wtf
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
"executor": "@nrwl/workspace:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.67.3/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.66.1/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useExplorerAssetQuery } from './__generated__/Asset';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import type { ComponentProps } from 'react';
|
||||
import Hash from '../hash';
|
||||
|
||||
export type AssetLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
id: string;
|
||||
@@ -28,7 +27,7 @@ const AssetLink = ({ id, ...props }: AssetLinkProps) => {
|
||||
|
||||
return (
|
||||
<Link className="underline" {...props} to={`/${Routes.ASSETS}#${id}`}>
|
||||
<Hash text={label} />
|
||||
{label}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Routes } from '../../../routes/route-names';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import type { ComponentProps } from 'react';
|
||||
import Hash from '../hash';
|
||||
|
||||
export type BlockLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
height: string;
|
||||
@@ -12,7 +11,7 @@ export type BlockLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
const BlockLink = ({ height, ...props }: BlockLinkProps) => {
|
||||
return (
|
||||
<Link className="underline" {...props} to={`/${Routes.BLOCKS}/${height}`}>
|
||||
<Hash text={height} />
|
||||
{height}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
import Hash from '../hash';
|
||||
|
||||
export enum EthExplorerLinkTypes {
|
||||
block = 'block',
|
||||
@@ -28,7 +27,7 @@ export const EthExplorerLink = ({
|
||||
{...props}
|
||||
href={link}
|
||||
>
|
||||
<Hash text={id} />
|
||||
{id}
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
export type HashProps = {
|
||||
text: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple component that ensures long text things like hashes
|
||||
* are broken when they need to wrap. This will remove the need
|
||||
* for a lot of the overflow scrolling that currently exists.
|
||||
*/
|
||||
const Hash = ({ text }: HashProps) => {
|
||||
return (
|
||||
<code className="break-all font-mono" style={{ wordWrap: 'break-word' }}>
|
||||
{text}
|
||||
</code>
|
||||
);
|
||||
};
|
||||
|
||||
export default Hash;
|
||||
@@ -8,9 +8,6 @@ query ExplorerMarket($id: ID!) {
|
||||
product {
|
||||
... on Future {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -8,7 +8,7 @@ export type ExplorerMarketQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null };
|
||||
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } | null };
|
||||
|
||||
|
||||
export const ExplorerMarketDocument = gql`
|
||||
@@ -22,9 +22,6 @@ export const ExplorerMarketDocument = gql`
|
||||
product {
|
||||
... on Future {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import React from 'react';
|
||||
import { Routes } from '../../../routes/route-names';
|
||||
import { useExplorerMarketQuery } from './__generated__/Market';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import type { ComponentProps } from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import Hash from '../hash';
|
||||
|
||||
export type MarketLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
id: string;
|
||||
showMarketName?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -16,11 +15,7 @@ export type MarketLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
* with a link to the markets list. If the name does not come back
|
||||
* it will use the ID instead
|
||||
*/
|
||||
const MarketLink = ({
|
||||
id,
|
||||
showMarketName = true,
|
||||
...props
|
||||
}: MarketLinkProps) => {
|
||||
const MarketLink = ({ id, ...props }: MarketLinkProps) => {
|
||||
const { data, error, loading } = useExplorerMarketQuery({
|
||||
variables: { id },
|
||||
});
|
||||
@@ -36,31 +31,17 @@ const MarketLink = ({
|
||||
<span role="img" aria-label="Unknown market" className="img">
|
||||
⚠️ {t('Invalid market')}
|
||||
</span>
|
||||
|
||||
<Hash text={id} />
|
||||
{id}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (showMarketName) {
|
||||
return (
|
||||
<Link
|
||||
className="underline"
|
||||
{...props}
|
||||
to={`/${Routes.MARKETS}#${id}`}
|
||||
title={id}
|
||||
>
|
||||
{label}
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Link className="underline" {...props} to={`/${Routes.MARKETS}#${id}`}>
|
||||
<Hash text={id} />
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Link className="underline" {...props} to={`/${Routes.MARKETS}#${id}`}>
|
||||
{label}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default MarketLink;
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useExplorerNodeQuery } from './__generated__/Node';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import type { ComponentProps } from 'react';
|
||||
import Hash from '../hash';
|
||||
|
||||
export type NodeLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
id: string;
|
||||
@@ -23,7 +22,7 @@ const NodeLink = ({ id, ...props }: NodeLinkProps) => {
|
||||
|
||||
return (
|
||||
<Link className="underline" {...props} to={`/${Routes.VALIDATORS}#${id}`}>
|
||||
<Hash text={label} />
|
||||
<code>{label}</code>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { Routes } from '../../../routes/route-names';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import type { ComponentProps } from 'react';
|
||||
import Hash from '../hash';
|
||||
|
||||
export type OracleLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
id: string;
|
||||
};
|
||||
|
||||
const OracleLink = ({ id, ...props }: OracleLinkProps) => {
|
||||
return (
|
||||
<Link
|
||||
className="underline font-mono"
|
||||
{...props}
|
||||
to={`/${Routes.ORACLES}/${id}`}
|
||||
>
|
||||
<Hash text={id} />
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default OracleLink;
|
||||
@@ -2,7 +2,6 @@ import { Routes } from '../../../routes/route-names';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import type { ComponentProps } from 'react';
|
||||
import Hash from '../hash';
|
||||
|
||||
export type PartyLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
id: string;
|
||||
@@ -15,7 +14,7 @@ const PartyLink = ({ id, ...props }: PartyLinkProps) => {
|
||||
{...props}
|
||||
to={`/${Routes.PARTIES}/${id}`}
|
||||
>
|
||||
<Hash text={id} />
|
||||
{id}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
query ExplorerProposal($id: ID!) {
|
||||
proposal(id: $id) {
|
||||
id
|
||||
rationale {
|
||||
title
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +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 ExplorerProposalQueryVariables = Types.Exact<{
|
||||
id: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null };
|
||||
|
||||
|
||||
export const ExplorerProposalDocument = gql`
|
||||
query ExplorerProposal($id: ID!) {
|
||||
proposal(id: $id) {
|
||||
id
|
||||
rationale {
|
||||
title
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useExplorerProposalQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useExplorerProposalQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useExplorerProposalQuery` 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 } = useExplorerProposalQuery({
|
||||
* variables: {
|
||||
* id: // value for 'id'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useExplorerProposalQuery(baseOptions: Apollo.QueryHookOptions<ExplorerProposalQuery, ExplorerProposalQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ExplorerProposalQuery, ExplorerProposalQueryVariables>(ExplorerProposalDocument, options);
|
||||
}
|
||||
export function useExplorerProposalLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerProposalQuery, ExplorerProposalQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ExplorerProposalQuery, ExplorerProposalQueryVariables>(ExplorerProposalDocument, options);
|
||||
}
|
||||
export type ExplorerProposalQueryHookResult = ReturnType<typeof useExplorerProposalQuery>;
|
||||
export type ExplorerProposalLazyQueryHookResult = ReturnType<typeof useExplorerProposalLazyQuery>;
|
||||
export type ExplorerProposalQueryResult = Apollo.QueryResult<ExplorerProposalQuery, ExplorerProposalQueryVariables>;
|
||||
@@ -1,82 +0,0 @@
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { render } from '@testing-library/react';
|
||||
import ProposalLink from './proposal-link';
|
||||
import { ExplorerProposalDocument } from './__generated__/Proposal';
|
||||
import { GraphQLError } from 'graphql';
|
||||
|
||||
function renderComponent(id: string, mocks: MockedResponse[]) {
|
||||
return (
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MemoryRouter>
|
||||
<ProposalLink id={id} />
|
||||
</MemoryRouter>
|
||||
</MockedProvider>
|
||||
);
|
||||
}
|
||||
|
||||
describe('Proposal link component', () => {
|
||||
it('Renders the ID at first', () => {
|
||||
const res = render(renderComponent('123', []));
|
||||
expect(res.getByText('123')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders the ID on error', async () => {
|
||||
const mock = {
|
||||
request: {
|
||||
query: ExplorerProposalDocument,
|
||||
variables: {
|
||||
id: '456',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
errors: [new GraphQLError('No such proposal')],
|
||||
},
|
||||
};
|
||||
const res = render(renderComponent('456', [mock]));
|
||||
// The ID
|
||||
expect(res.getByText('456')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders the proposal title when the query returns a result', async () => {
|
||||
const mock = {
|
||||
request: {
|
||||
query: ExplorerProposalDocument,
|
||||
variables: {
|
||||
id: '123',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
proposal: {
|
||||
id: '123',
|
||||
rationale: {
|
||||
title: 'test-title',
|
||||
description: 'test description',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const res = render(renderComponent('123', [mock]));
|
||||
expect(res.getByText('123')).toBeInTheDocument();
|
||||
expect(await res.findByText('test-title')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Leaves the proposal id when the market is not found', async () => {
|
||||
const mock = {
|
||||
request: {
|
||||
query: ExplorerProposalDocument,
|
||||
variables: {
|
||||
id: '123',
|
||||
},
|
||||
},
|
||||
error: new Error('No such asset'),
|
||||
};
|
||||
|
||||
const res = render(renderComponent('123', [mock]));
|
||||
expect(await res.findByText('123')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,28 +0,0 @@
|
||||
import { useExplorerProposalQuery } from './__generated__/Proposal';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { ENV } from '../../../config/env';
|
||||
import Hash from '../hash';
|
||||
export type ProposalLinkProps = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a proposal ID, generates an external link over to
|
||||
* the Governance page for more information
|
||||
*/
|
||||
const ProposalLink = ({ id }: ProposalLinkProps) => {
|
||||
const { data } = useExplorerProposalQuery({
|
||||
variables: { id },
|
||||
});
|
||||
|
||||
const base = ENV.dataSources.governanceUrl;
|
||||
const label = data?.proposal?.rationale.title || id;
|
||||
|
||||
return (
|
||||
<ExternalLink href={`${base}/proposals/${id}`}>
|
||||
<Hash text={label} />
|
||||
</ExternalLink>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProposalLink;
|
||||
@@ -97,10 +97,6 @@ describe('Order TX Summary component', () => {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'TEST',
|
||||
settlementAsset: {
|
||||
__typeName: 'SettlementAsset',
|
||||
decimals: 18,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,75 +3,58 @@ import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { render } from '@testing-library/react';
|
||||
import PriceInMarket from './price-in-market';
|
||||
import type { DecimalSource } from './price-in-market';
|
||||
import { ExplorerMarketDocument } from '../links/market-link/__generated__/Market';
|
||||
|
||||
function renderComponent(
|
||||
price: string,
|
||||
marketId: string,
|
||||
mocks: MockedResponse[],
|
||||
decimalSource: DecimalSource = 'MARKET'
|
||||
mocks: MockedResponse[]
|
||||
) {
|
||||
return (
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MemoryRouter>
|
||||
<PriceInMarket
|
||||
marketId={marketId}
|
||||
price={price}
|
||||
decimalSource={decimalSource}
|
||||
/>
|
||||
<PriceInMarket marketId={marketId} price={price} />
|
||||
</MemoryRouter>
|
||||
</MockedProvider>
|
||||
);
|
||||
}
|
||||
|
||||
const fullMock = {
|
||||
request: {
|
||||
query: ExplorerMarketDocument,
|
||||
variables: {
|
||||
id: '123',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
market: {
|
||||
id: '123',
|
||||
decimalPlaces: 2,
|
||||
state: 'irrelevant-test-data',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'test dai',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'dai',
|
||||
settlementAsset: {
|
||||
decimals: 18,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe('Price in Market component', () => {
|
||||
it('Renders the raw price when there is no market data', () => {
|
||||
const res = render(renderComponent('100', '123', []));
|
||||
expect(res.getByText('100')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders the formatted price when market data is fetched, using market decimals by default', async () => {
|
||||
const res = render(renderComponent('100', '123', [fullMock]));
|
||||
expect(await res.findByText('1.00')).toBeInTheDocument();
|
||||
expect(await res.findByText('dai')).toBeInTheDocument();
|
||||
});
|
||||
it('Renders the formatted price when market data is fetched', async () => {
|
||||
const mock = {
|
||||
request: {
|
||||
query: ExplorerMarketDocument,
|
||||
variables: {
|
||||
id: '123',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
market: {
|
||||
id: '123',
|
||||
decimalPlaces: 2,
|
||||
state: 'irrelevant-test-data',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'test dai',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'dai',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
it('Renders the formatted price when market data is fetched, using settlement decimals', async () => {
|
||||
const res = render(
|
||||
renderComponent('100', '123', [fullMock], 'SETTLEMENT_ASSET')
|
||||
);
|
||||
expect(await res.findByText('0.0000000000000001')).toBeInTheDocument();
|
||||
const res = render(renderComponent('100', '123', [mock]));
|
||||
expect(await res.findByText('1.00')).toBeInTheDocument();
|
||||
expect(await res.findByText('dai')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
||||
@@ -3,23 +3,16 @@ import isUndefined from 'lodash/isUndefined';
|
||||
import { useExplorerMarketQuery } from '../links/market-link/__generated__/Market';
|
||||
import get from 'lodash/get';
|
||||
|
||||
export type DecimalSource = 'MARKET' | 'SETTLEMENT_ASSET';
|
||||
|
||||
export type PriceInMarketProps = {
|
||||
marketId: string;
|
||||
price: string;
|
||||
decimalSource?: DecimalSource;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a market ID and a price it will fetch the market
|
||||
* and format the price in that market's decimal places.
|
||||
*/
|
||||
const PriceInMarket = ({
|
||||
marketId,
|
||||
price,
|
||||
decimalSource = 'MARKET',
|
||||
}: PriceInMarketProps) => {
|
||||
const PriceInMarket = ({ marketId, price }: PriceInMarketProps) => {
|
||||
const { data } = useExplorerMarketQuery({
|
||||
variables: { id: marketId },
|
||||
fetchPolicy: 'cache-first',
|
||||
@@ -27,19 +20,8 @@ const PriceInMarket = ({
|
||||
|
||||
let label = price;
|
||||
|
||||
if (data) {
|
||||
if (decimalSource === 'MARKET' && data.market?.decimalPlaces) {
|
||||
label = addDecimalsFormatNumber(price, data.market.decimalPlaces);
|
||||
} else if (
|
||||
decimalSource === 'SETTLEMENT_ASSET' &&
|
||||
data.market?.tradableInstrument.instrument.product.settlementAsset
|
||||
) {
|
||||
label = addDecimalsFormatNumber(
|
||||
price,
|
||||
data.market?.tradableInstrument.instrument.product.settlementAsset
|
||||
.decimals
|
||||
);
|
||||
}
|
||||
if (data && data.market?.decimalPlaces) {
|
||||
label = addDecimalsFormatNumber(price, data.market.decimalPlaces);
|
||||
}
|
||||
|
||||
const suffix = get(
|
||||
|
||||
+4
-10
@@ -63,21 +63,15 @@ describe('Chain Event: Builtin asset deposit', () => {
|
||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||
const partyLink = screen.getByText(`${fullMock.partyId}`);
|
||||
expect(partyLink).toBeInTheDocument();
|
||||
if (!partyLink.parentElement) {
|
||||
throw new Error('Party link does not exist');
|
||||
}
|
||||
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(partyLink.tagName).toEqual('A');
|
||||
expect(partyLink.getAttribute('href')).toEqual(
|
||||
`/parties/${fullMock.partyId}`
|
||||
);
|
||||
|
||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||
expect(assetLink).toBeInTheDocument();
|
||||
if (!assetLink.parentElement) {
|
||||
throw new Error('Asset link does not exist');
|
||||
}
|
||||
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(assetLink.tagName).toEqual('A');
|
||||
expect(assetLink.getAttribute('href')).toEqual(
|
||||
`/assets#${fullMock.vegaAssetId}`
|
||||
);
|
||||
});
|
||||
|
||||
+4
-10
@@ -69,21 +69,15 @@ describe('Chain Event: Builtin asset withdrawal', () => {
|
||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||
const partyLink = screen.getByText(`${fullMock.partyId}`);
|
||||
expect(partyLink).toBeInTheDocument();
|
||||
if (!partyLink.parentElement) {
|
||||
throw new Error('Party link does not exist');
|
||||
}
|
||||
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(partyLink.tagName).toEqual('A');
|
||||
expect(partyLink.getAttribute('href')).toEqual(
|
||||
`/parties/${fullMock.partyId}`
|
||||
);
|
||||
|
||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||
expect(assetLink).toBeInTheDocument();
|
||||
if (!assetLink.parentElement) {
|
||||
throw new Error('Asset link does not exist');
|
||||
}
|
||||
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(assetLink.tagName).toEqual('A');
|
||||
expect(assetLink.getAttribute('href')).toEqual(
|
||||
`/assets#${fullMock.vegaAssetId}`
|
||||
);
|
||||
});
|
||||
|
||||
+2
-5
@@ -60,11 +60,8 @@ describe('Chain Event: ERC20 Asset Delist', () => {
|
||||
|
||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||
expect(assetLink).toBeInTheDocument();
|
||||
if (!assetLink.parentElement) {
|
||||
throw new Error('Asset link does not exist');
|
||||
}
|
||||
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(assetLink.tagName).toEqual('A');
|
||||
expect(assetLink.getAttribute('href')).toEqual(
|
||||
`/assets#${fullMock.vegaAssetId}`
|
||||
);
|
||||
});
|
||||
|
||||
+3
-9
@@ -76,20 +76,14 @@ describe('Chain Event: ERC20 Asset limits updated', () => {
|
||||
expect(screen.getByText(t('Vega asset'))).toBeInTheDocument();
|
||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||
expect(assetLink).toBeInTheDocument();
|
||||
if (!assetLink.parentElement) {
|
||||
throw new Error('Asset link does not exist');
|
||||
}
|
||||
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(assetLink.tagName).toEqual('A');
|
||||
expect(assetLink.getAttribute('href')).toEqual(
|
||||
`/assets#${fullMock.vegaAssetId}`
|
||||
);
|
||||
|
||||
expect(screen.getByText(t('ERC20 asset'))).toBeInTheDocument();
|
||||
const ethLink = screen.getByText(`${fullMock.sourceEthereumAddress}`);
|
||||
if (!ethLink.parentElement) {
|
||||
throw new Error('ETH link does not exist');
|
||||
}
|
||||
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||
expect(ethLink.getAttribute('href')).toContain(
|
||||
`/address/${fullMock.sourceEthereumAddress}`
|
||||
);
|
||||
});
|
||||
|
||||
+3
-9
@@ -62,20 +62,14 @@ describe('Chain Event: ERC20 Asset List', () => {
|
||||
expect(screen.getByText(t('Added Vega asset'))).toBeInTheDocument();
|
||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||
expect(assetLink).toBeInTheDocument();
|
||||
if (!assetLink.parentElement) {
|
||||
throw new Error('Asset link does not exist');
|
||||
}
|
||||
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(assetLink.tagName).toEqual('A');
|
||||
expect(assetLink.getAttribute('href')).toEqual(
|
||||
`/assets#${fullMock.vegaAssetId}`
|
||||
);
|
||||
|
||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||
const ethLink = screen.getByText(`${fullMock.assetSource}`);
|
||||
if (!ethLink.parentElement) {
|
||||
throw new Error('Asset link does not exist');
|
||||
}
|
||||
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||
expect(ethLink.getAttribute('href')).toContain(
|
||||
`/address/${fullMock.assetSource}`
|
||||
);
|
||||
});
|
||||
|
||||
+5
-14
@@ -62,30 +62,21 @@ describe('Chain Event: ERC20 asset deposit', () => {
|
||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||
const partyLink = screen.getByText(`${fullMock.targetPartyId}`);
|
||||
expect(partyLink).toBeInTheDocument();
|
||||
if (!partyLink.parentElement) {
|
||||
throw new Error('Party link does not exist');
|
||||
}
|
||||
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(partyLink.tagName).toEqual('A');
|
||||
expect(partyLink.getAttribute('href')).toEqual(
|
||||
`/parties/${fullMock.targetPartyId}`
|
||||
);
|
||||
|
||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||
expect(assetLink).toBeInTheDocument();
|
||||
if (!assetLink.parentElement) {
|
||||
throw new Error('Asset link does not exist');
|
||||
}
|
||||
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(assetLink.tagName).toEqual('A');
|
||||
expect(assetLink.getAttribute('href')).toEqual(
|
||||
`/assets#${fullMock.vegaAssetId}`
|
||||
);
|
||||
|
||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||
const ethLink = screen.getByText(`${fullMock.sourceEthereumAddress}`);
|
||||
if (!ethLink.parentElement) {
|
||||
throw new Error('ETH link does not exist');
|
||||
}
|
||||
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||
expect(ethLink.getAttribute('href')).toContain(
|
||||
`/address/${fullMock.sourceEthereumAddress}`
|
||||
);
|
||||
});
|
||||
|
||||
+3
-9
@@ -57,20 +57,14 @@ describe('Chain Event: ERC20 asset deposit', () => {
|
||||
expect(screen.getByText(t('Asset'))).toBeInTheDocument();
|
||||
const assetLink = screen.getByText(`${fullMock.vegaAssetId}`);
|
||||
expect(assetLink).toBeInTheDocument();
|
||||
if (!assetLink.parentElement) {
|
||||
throw new Error('Asset link does not exist');
|
||||
}
|
||||
expect(assetLink.parentElement.tagName).toEqual('A');
|
||||
expect(assetLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(assetLink.tagName).toEqual('A');
|
||||
expect(assetLink.getAttribute('href')).toEqual(
|
||||
`/assets#${fullMock.vegaAssetId}`
|
||||
);
|
||||
|
||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||
const ethLink = screen.getByText(`${fullMock.targetEthereumAddress}`);
|
||||
if (!ethLink.parentElement) {
|
||||
throw new Error('ETH link does not exist');
|
||||
}
|
||||
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||
expect(ethLink.getAttribute('href')).toContain(
|
||||
`/address/${fullMock.targetEthereumAddress}`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -64,20 +64,14 @@ describe('Chain Event: Stake deposit', () => {
|
||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||
const partyLink = screen.getByText(`${fullMock.vegaPublicKey}`);
|
||||
expect(partyLink).toBeInTheDocument();
|
||||
if (!partyLink.parentElement) {
|
||||
throw new Error('Party link does not exist');
|
||||
}
|
||||
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(partyLink.tagName).toEqual('A');
|
||||
expect(partyLink.getAttribute('href')).toEqual(
|
||||
`/parties/${fullMock.vegaPublicKey}`
|
||||
);
|
||||
|
||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||
const ethLink = screen.getByText(`${fullMock.ethereumAddress}`);
|
||||
if (!ethLink.parentElement) {
|
||||
throw new Error('ETH link does not exist');
|
||||
}
|
||||
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||
expect(ethLink.getAttribute('href')).toContain(
|
||||
`/address/${fullMock.ethereumAddress}`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -64,20 +64,14 @@ describe('Chain Event: Stake remove', () => {
|
||||
expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
|
||||
const partyLink = screen.getByText(`${fullMock.vegaPublicKey}`);
|
||||
expect(partyLink).toBeInTheDocument();
|
||||
if (!partyLink.parentElement) {
|
||||
throw new Error('Party link does not exist');
|
||||
}
|
||||
expect(partyLink.parentElement.tagName).toEqual('A');
|
||||
expect(partyLink.parentElement.getAttribute('href')).toEqual(
|
||||
expect(partyLink.tagName).toEqual('A');
|
||||
expect(partyLink.getAttribute('href')).toEqual(
|
||||
`/parties/${fullMock.vegaPublicKey}`
|
||||
);
|
||||
|
||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||
const ethLink = screen.getByText(`${fullMock.ethereumAddress}`);
|
||||
if (!ethLink.parentElement) {
|
||||
throw new Error('ETH link does not exist');
|
||||
}
|
||||
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||
expect(ethLink.getAttribute('href')).toContain(
|
||||
`/address/${fullMock.ethereumAddress}`
|
||||
);
|
||||
});
|
||||
|
||||
+1
-4
@@ -66,10 +66,7 @@ describe('Chain Event: Stake total supply change', () => {
|
||||
|
||||
expect(screen.getByText(t('Source'))).toBeInTheDocument();
|
||||
const ethLink = screen.getByText(`${fullMock.tokenAddress}`);
|
||||
if (!ethLink.parentElement) {
|
||||
throw new Error('ETH link does not exist');
|
||||
}
|
||||
expect(ethLink.parentElement.getAttribute('href')).toContain(
|
||||
expect(ethLink.getAttribute('href')).toContain(
|
||||
`/address/${fullMock.tokenAddress}`
|
||||
);
|
||||
});
|
||||
|
||||
+11
@@ -2,5 +2,16 @@ query ExplorerSettlementAssetForMarket($id: ID!) {
|
||||
market(id: $id) {
|
||||
id
|
||||
decimalPlaces
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
product {
|
||||
... on Future {
|
||||
settlementAsset {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-1
@@ -8,7 +8,7 @@ export type ExplorerSettlementAssetForMarketQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerSettlementAssetForMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number } | null };
|
||||
export type ExplorerSettlementAssetForMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null };
|
||||
|
||||
|
||||
export const ExplorerSettlementAssetForMarketDocument = gql`
|
||||
@@ -16,6 +16,17 @@ export const ExplorerSettlementAssetForMarketDocument = gql`
|
||||
market(id: $id) {
|
||||
id
|
||||
decimalPlaces
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
product {
|
||||
... on Future {
|
||||
settlementAsset {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
+2
-2
@@ -91,7 +91,7 @@ describe('LiquidityProvisionDetails component', () => {
|
||||
expect(res.getByTestId('SIDE_SELL-40-1')).toBeInTheDocument();
|
||||
expect(res.getByText('-1')).toBeInTheDocument();
|
||||
expect(res.getByText('Best Bid')).toBeInTheDocument();
|
||||
expect(res.getByText('40%')).toBeInTheDocument();
|
||||
expect(res.getByText('40% (normalised from: 20%)')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('handles a missing offset gracefully (should not happen)', () => {
|
||||
@@ -125,7 +125,7 @@ describe('LiquidityProvisionDetails component', () => {
|
||||
);
|
||||
// Row test ids and keys are based on the side, reference and proportion - and that proportion is scaled
|
||||
expect(res.getByTestId('SIDE_SELL-40-1')).toBeInTheDocument();
|
||||
expect(res.getByText('40%')).toBeInTheDocument();
|
||||
expect(res.getByText('40% (normalised from: 20%)')).toBeInTheDocument();
|
||||
expect(res.getByText('-')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
+5
-1
@@ -67,7 +67,11 @@ export function LiquidityProvisionDetailsRow({
|
||||
<td className="text-center">
|
||||
{order.reference ? LiquidityReferenceLabel[order.reference] : '-'}
|
||||
</td>
|
||||
<td className="text-center">{proportion}%</td>
|
||||
<td className="text-center">
|
||||
{proportion === order.proportion
|
||||
? `${proportion}%`
|
||||
: `${proportion}% (normalised from: ${order.proportion}%)`}{' '}
|
||||
</td>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
+9
@@ -13,6 +13,15 @@ const decimalsMock: ExplorerSettlementAssetForMarketQuery = {
|
||||
id: '123',
|
||||
__typename: 'Market',
|
||||
decimalPlaces: 5,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
settlementAsset: {
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+4
-2
@@ -36,7 +36,7 @@ export function LiquidityProvisionOffset({
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the work of formatting the number now we have the market decimal places.
|
||||
* Does the work of formatting the number now we have the settlement decimal places.
|
||||
* If no market data is assigned (i.e. during loading, or if the market doesn't exist)
|
||||
* this function will return the unformatted number
|
||||
*
|
||||
@@ -49,7 +49,9 @@ export function getFormattedOffset(
|
||||
offset: string,
|
||||
data?: ExplorerSettlementAssetForMarketQuery
|
||||
) {
|
||||
const decimals = data?.market?.decimalPlaces;
|
||||
const decimals =
|
||||
data?.market?.tradableInstrument.instrument.product.settlementAsset
|
||||
.decimals;
|
||||
|
||||
if (!decimals) {
|
||||
return offset;
|
||||
|
||||
+2
-2
@@ -203,7 +203,7 @@ describe('LiquidityProvisionDetails component', () => {
|
||||
};
|
||||
|
||||
const res = renderComponent(mock);
|
||||
expect(res.getByText('45%')).toBeInTheDocument();
|
||||
expect(res.getByText('55%')).toBeInTheDocument();
|
||||
expect(res.getByText('45% (normalised from: 25%)')).toBeInTheDocument();
|
||||
expect(res.getByText('55% (normalised from: 30%)')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import { JSONOracleData, parseData } from './data-submission-json-oracle';
|
||||
|
||||
describe('JSONOracleData', () => {
|
||||
it('renders a code block if there is a payload that is base64 encoded', () => {
|
||||
const p = 'eyJwcmljZXMuRVRIOTkudmFsdWUiOiAiMTMwNTAwMDAwMCJ9';
|
||||
const screen = render(<JSONOracleData payload={p} />);
|
||||
expect(screen.getByTestId('json-code')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders an error if b64 decoding fails', () => {
|
||||
const p = 'not-encoded';
|
||||
const screen = render(<JSONOracleData payload={p} />);
|
||||
|
||||
expect(
|
||||
screen.getByText('Awaiting Block Explorer transaction details')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Parse JSON oracle data', () => {
|
||||
it('returns null for an invalid b64 string', () => {
|
||||
expect(parseData('🤷')).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for a string that looks like an object', () => {
|
||||
expect(parseData('{}')).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for null', () => {
|
||||
expect(parseData(null as unknown as string)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns a string for b64 encoded data', () => {
|
||||
const res = parseData('dGVzdCA9IHRydWU=');
|
||||
expect(typeof res).toEqual('string');
|
||||
expect(res).toEqual('test = true');
|
||||
});
|
||||
|
||||
it('returns a string for b64 encoded json, without any extra parsing', () => {
|
||||
const res = parseData('eyJ0ZXN0Ijp0cnVlfQ==');
|
||||
expect(typeof res).toEqual('string');
|
||||
expect(res).toEqual('{"test":true}');
|
||||
});
|
||||
});
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
|
||||
interface JSONOracleDataProps {
|
||||
payload: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a JSON oracle. Given the shape could be any valid JSON,
|
||||
* this doesn't try to do anything smart - it just renders the message
|
||||
*/
|
||||
export const JSONOracleData = ({ payload }: JSONOracleDataProps) => {
|
||||
const decodedSubmission = parseData(payload);
|
||||
|
||||
if (!decodedSubmission) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<section>
|
||||
<code data-testid="json-code">{decodedSubmission}</code>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely parses the JSON Oracle payload
|
||||
*
|
||||
* @param payload base64 encoded JSON
|
||||
* @returns Object or null
|
||||
*/
|
||||
export function parseData(payload: string) {
|
||||
try {
|
||||
if (!payload || typeof payload !== 'string') {
|
||||
throw new Error('Not a string');
|
||||
}
|
||||
return atob(payload);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import { OpenOracleData, parseData } from './data-submission-open-oracle';
|
||||
|
||||
describe('OpenOracleData', () => {
|
||||
it('renders a table if there is data', () => {
|
||||
const p =
|
||||
'eyJtZXNzYWdlcyI6IFsiMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA2M2M3ZTMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNGYxZjM4ZWEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjcwNzI2OTYzNjU3MzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNDI1NDQzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCJdLCAicHJpY2VzIjogeyJFVEgiOiIxMjMifSwgInNpZ25hdHVyZXMiOiBbIjB4N2U0Nzc2OWEyNzI5NzIwN2Q5ZTIyMmM3YTY2YjBlYzk3Njg4MWY3NmVkYjg5OGFhYzQ5OTRlZWYwOTc4MmI3NGUxMGE5MTJmZWQ1Y2E3NmFlN2U3NzVjOWZiOTBjZGE4ZjhkMDhlNzUyOTE1NzQ2ZTY2OGE1ZWM3OWRmOTZmNmQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDFjIl0sICJ0aW1lc3RhbXAiOiAiMTIzIn0=';
|
||||
|
||||
const screen = render(<OpenOracleData payload={p} />);
|
||||
expect(screen.getByTestId('decoded-payload')).toBeInTheDocument();
|
||||
expect(screen.getByText('ETH')).toBeInTheDocument();
|
||||
expect(screen.getByText('123')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders an error if decoding fails', () => {
|
||||
const p = 'not-encoded';
|
||||
const screen = render(<OpenOracleData payload={p} />);
|
||||
|
||||
expect(
|
||||
screen.getByText('Awaiting Block Explorer transaction details')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Parse Open oracle data', () => {
|
||||
it('returns null for an invalid b64 string', () => {
|
||||
expect(parseData('🤷')).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for a string that looks like an object', () => {
|
||||
expect(parseData('{}')).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for null', () => {
|
||||
expect(parseData(null as unknown as string)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns a string for b64 encoded data', () => {
|
||||
const res = parseData('dGVzdCA9IHRydWU=');
|
||||
expect(res).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null if the parsed object does not look like te right shape', () => {
|
||||
// Encoded: {"test":true}
|
||||
const res = parseData('eyJ0ZXN0Ijp0cnVlfQ==');
|
||||
expect(res).toBeNull();
|
||||
});
|
||||
|
||||
it('returns an object if the payload parses and looks fine', () => {
|
||||
// Encoded: {"messages": [], "prices": {}, "signatures": [], "timestamp": "123"}
|
||||
const res = parseData(
|
||||
'eyJtZXNzYWdlcyI6IFtdLCAicHJpY2VzIjoge30sICJzaWduYXR1cmVzIjogW10sICJ0aW1lc3RhbXAiOiAiMTIzIn0='
|
||||
);
|
||||
expect(typeof res.prices).toEqual('object');
|
||||
expect(Array.isArray(res.messages)).toBeTruthy();
|
||||
expect(Array.isArray(res.signatures)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { NestedDataList } from '../../../nested-data-list';
|
||||
import { OpenOraclePrices } from './open-oracle/open-oracle-prices';
|
||||
|
||||
interface OpenOracleDataProps {
|
||||
payload: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes Open Oracle data based on it's main parts:
|
||||
* - messages
|
||||
* - signatures
|
||||
* - prices
|
||||
*/
|
||||
export const OpenOracleData = ({ payload }: OpenOracleDataProps) => {
|
||||
const decodedSubmission = parseData(payload);
|
||||
|
||||
if (!decodedSubmission) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const date = decodedSubmission.timestamp;
|
||||
const formattedDate = new Date(date * 1000).toLocaleString();
|
||||
|
||||
return (
|
||||
<section>
|
||||
<span>{formattedDate}</span>
|
||||
<code>
|
||||
<OpenOraclePrices
|
||||
prices={decodedSubmission.prices}
|
||||
messages={decodedSubmission.messages}
|
||||
signatures={decodedSubmission.signatures}
|
||||
/>
|
||||
</code>
|
||||
<details data-testid="decoded-payload">
|
||||
<summary>{t('Decoded payload')}</summary>
|
||||
<NestedDataList data={decodedSubmission} />
|
||||
</details>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely parses the Open Oracle payload
|
||||
*
|
||||
* @param payload base64 encoded JSON
|
||||
* @returns Object or null
|
||||
*/
|
||||
export function parseData(payload: string) {
|
||||
try {
|
||||
if (!payload || typeof payload !== 'string') {
|
||||
throw new Error('Not a string');
|
||||
}
|
||||
|
||||
const res = JSON.parse(atob(payload));
|
||||
if (!res.prices || !res.messages || !res.signatures) {
|
||||
throw new Error('Not an open oracle format message');
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import { OpenOraclePrices } from './open-oracle-prices';
|
||||
import type { Price } from './open-oracle-prices';
|
||||
|
||||
describe('OpenOraclePrices', () => {
|
||||
it('Will not render with no prices', () => {
|
||||
const p = undefined as unknown as Price;
|
||||
const m: string[] = [];
|
||||
const s: string[] = [];
|
||||
const screen = render(
|
||||
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||
);
|
||||
expect(screen.container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
it('Will not render with no messages', () => {
|
||||
const m = undefined as unknown as string[];
|
||||
const p: Price = {};
|
||||
const s: string[] = [];
|
||||
const screen = render(
|
||||
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||
);
|
||||
expect(screen.container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
it('will not render with no signatures', () => {
|
||||
const s = undefined as unknown as string[];
|
||||
const m: string[] = [];
|
||||
const p: Price = {};
|
||||
const screen = render(
|
||||
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||
);
|
||||
expect(screen.container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
it('will not render with mismatched prices/signatures', () => {
|
||||
const p: Price = { ETH: '123' };
|
||||
const m = ['0x123', '0x456'];
|
||||
const s: string[] = [];
|
||||
const screen = render(
|
||||
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||
);
|
||||
expect(screen.container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
it('will not render with mismatched signatures and messages', () => {
|
||||
const p: Price = { ETH: '123', BTC: '12' };
|
||||
const s = ['0xcac', '0xb33f'];
|
||||
const m = ['0x1204o42c', '0xb3ddd3f', '0x9999'];
|
||||
|
||||
const screen = render(
|
||||
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||
);
|
||||
expect(screen.container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
it('renders a table when there are prices and signatures and messages', () => {
|
||||
const p: Price = { ETH: '123', BTC: '12' };
|
||||
const s = ['0xcac', '0xb33f'];
|
||||
const m = ['0x120442c', '0xb3ddd3f'];
|
||||
|
||||
const screen = render(
|
||||
<OpenOraclePrices prices={p} messages={m} signatures={s} />
|
||||
);
|
||||
expect(screen.getByTestId('openoracleprices')).toBeInTheDocument();
|
||||
|
||||
// Table headings
|
||||
expect(screen.getByText('Asset')).toBeInTheDocument();
|
||||
expect(screen.getByText('Price')).toBeInTheDocument();
|
||||
expect(screen.getByText('Signature')).toBeInTheDocument();
|
||||
expect(screen.getByText('Message')).toBeInTheDocument();
|
||||
// Disabled - see vegaprotocol/frontend-monorepo#/2726
|
||||
// expect(screen.getByText('Signer')).toBeInTheDocument();
|
||||
|
||||
// One row per asset
|
||||
expect(screen.getByText('ETH')).toBeInTheDocument();
|
||||
expect(screen.getByText('123')).toBeInTheDocument();
|
||||
expect(screen.getByText('0xcac')).toBeInTheDocument();
|
||||
expect(screen.getByText('0xb33f')).toBeInTheDocument();
|
||||
// Does not test signer element for this row
|
||||
|
||||
expect(screen.getByText('BTC')).toBeInTheDocument();
|
||||
expect(screen.getByText('12')).toBeInTheDocument();
|
||||
expect(screen.getByText('0x120442c')).toBeInTheDocument();
|
||||
expect(screen.getByText('0xb3ddd3f')).toBeInTheDocument();
|
||||
// Does not test signer element for this row
|
||||
});
|
||||
});
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { CopyWithTooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import { TableRow } from '../../../../table';
|
||||
import { TruncateInline } from '../../../../truncate/truncate';
|
||||
import { utils } from 'ethers';
|
||||
|
||||
export type Price = {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
interface OpenOraclePricesProps {
|
||||
prices: Price;
|
||||
signatures: string[];
|
||||
messages: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Oracle price table, showing the entries in this
|
||||
* decoded message
|
||||
*
|
||||
* Notes:
|
||||
* - Signer is derived by recovering the address from the
|
||||
* signature and the message. This is currently disabled
|
||||
* as the implementation is incorrect
|
||||
*/
|
||||
export function OpenOraclePrices({
|
||||
prices,
|
||||
messages,
|
||||
signatures,
|
||||
}: OpenOraclePricesProps) {
|
||||
if (
|
||||
!prices ||
|
||||
!messages ||
|
||||
!signatures ||
|
||||
Object.keys(prices).length !== messages.length ||
|
||||
signatures.length !== messages.length
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<table data-testid="openoracleprices">
|
||||
<thead>
|
||||
<TableRow modifier="bordered">
|
||||
<th>{t('Asset')}</th>
|
||||
<th className="text-right">{t('Price')}</th>
|
||||
<th>{t('Signature')}</th>
|
||||
<th>{t('Message')}</th>
|
||||
{/* <th>{t('Signer')}</th> */}
|
||||
</TableRow>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.keys(prices).map((k: string, i: number) => {
|
||||
if (k && prices[k]) {
|
||||
const message = messages[i];
|
||||
const signature = signatures[i];
|
||||
return (
|
||||
<OpenOraclePrice
|
||||
key={`price-${i}`}
|
||||
asset={k}
|
||||
value={prices[k]}
|
||||
message={message}
|
||||
signature={signature}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
|
||||
type OpenOraclePriceProps = {
|
||||
asset: string;
|
||||
value: string;
|
||||
message: string;
|
||||
signature: string;
|
||||
};
|
||||
|
||||
export function OpenOraclePrice({
|
||||
asset,
|
||||
value,
|
||||
signature,
|
||||
message,
|
||||
}: OpenOraclePriceProps) {
|
||||
// const addr = getAddressFromMessageAndSignature(message, signature);
|
||||
return (
|
||||
<TableRow modifier="bordered" key={`${asset}`}>
|
||||
<td className="px-4">{asset}</td>
|
||||
<td className="px-4 text-right">{value}</td>
|
||||
<td className="px-4">
|
||||
<CopyWithTooltip text={signature}>
|
||||
<button>
|
||||
<TruncateInline text={signature} startChars={5} endChars={5} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
</td>
|
||||
<td className="px-4">
|
||||
<CopyWithTooltip text={message}>
|
||||
<button>
|
||||
<TruncateInline text={message} startChars={5} endChars={5} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
</td>
|
||||
{/*<td className="px-4">
|
||||
<CopyWithTooltip text={message}>
|
||||
<button>
|
||||
<TruncateInline text={addr} startChars={5} endChars={5} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
</td> */}
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
export function getAddressFromMessageAndSignature(
|
||||
message: string,
|
||||
signature: string
|
||||
) {
|
||||
try {
|
||||
const m = utils.hashMessage(utils.arrayify(utils.keccak256(message)));
|
||||
const s = utils.splitSignature(
|
||||
signature.slice(0, 130) + signature.slice(-2)
|
||||
);
|
||||
|
||||
return utils.recoverAddress(m, s);
|
||||
} catch (e) {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,6 @@ import type { BlockExplorerTransactionResult } from '../../../../routes/types/bl
|
||||
import type { TendermintBlocksResponse } from '../../../../routes/blocks/tendermint-blocks-response';
|
||||
import { Time } from '../../../time';
|
||||
import { ChainResponseCode } from '../chain-response-code/chain-reponse.code';
|
||||
import { TxDataView } from '../../tx-data-view';
|
||||
import Hash from '../../../links/hash';
|
||||
|
||||
interface TxDetailsSharedProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@@ -48,7 +46,7 @@ export const TxDetailsShared = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell {...sharedHeaderProps}>{t('Hash')}</TableCell>
|
||||
<TableCell>
|
||||
<Hash text={txData.hash} />
|
||||
<code>{txData.hash}</code>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
@@ -84,12 +82,6 @@ export const TxDetailsShared = ({
|
||||
<ChainResponseCode code={txData.code} error={txData.error} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell {...sharedHeaderProps}>{t('Transaction')}</TableCell>
|
||||
<TableCell>
|
||||
<TxDataView blockData={blockData} txData={txData} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
import { TableWithTbody } from '../../table';
|
||||
import type { components } from '../../../../types/explorer';
|
||||
import { OpenOracleData } from './oracle-data/data-submission-open-oracle';
|
||||
import { JSONOracleData } from './oracle-data/data-submission-json-oracle';
|
||||
|
||||
export type OracleSubmissionSource =
|
||||
components['schemas']['OracleDataSubmissionOracleSource'];
|
||||
|
||||
interface TxDetailsDataSubmissionProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
pubKey: string | undefined;
|
||||
blockData: TendermintBlocksResponse | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Someone cancelled an order
|
||||
*/
|
||||
export const TxDetailsDataSubmission = ({
|
||||
txData,
|
||||
pubKey,
|
||||
blockData,
|
||||
}: TxDetailsDataSubmissionProps) => {
|
||||
if (!txData || !txData.command.oracleDataSubmission) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const type: OracleSubmissionSource =
|
||||
txData.command.oracleDataSubmission.source;
|
||||
if (!type) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const payload = txData.command.oracleDataSubmission.payload;
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableWithTbody className="mb-8">
|
||||
<TxDetailsShared
|
||||
txData={txData}
|
||||
pubKey={pubKey}
|
||||
blockData={blockData}
|
||||
/>
|
||||
</TableWithTbody>
|
||||
{type === 'ORACLE_SOURCE_OPEN_ORACLE' ? (
|
||||
<OpenOracleData payload={payload} />
|
||||
) : (
|
||||
<JSONOracleData payload={payload} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -8,8 +8,10 @@ import { TxDetailsHeartbeat } from './tx-hearbeat';
|
||||
import { TxDetailsGeneric } from './tx-generic';
|
||||
import { TxDetailsBatch } from './tx-batch';
|
||||
import { TxDetailsChainEvent } from './tx-chain-event';
|
||||
import { TxContent } from '../../../routes/txs/id/tx-content';
|
||||
import { TxDetailsNodeVote } from './tx-node-vote';
|
||||
import { TxDetailsOrderCancel } from './tx-order-cancel';
|
||||
import get from 'lodash/get';
|
||||
import { TxDetailsOrderAmend } from './tx-order-amend';
|
||||
import { TxDetailsWithdrawSubmission } from './tx-withdraw-submission';
|
||||
import { TxDetailsDelegate } from './tx-delegation';
|
||||
@@ -17,8 +19,6 @@ import { TxDetailsUndelegate } from './tx-undelegation';
|
||||
import { TxDetailsLiquiditySubmission } from './tx-liquidity-submission';
|
||||
import { TxDetailsLiquidityAmendment } from './tx-liquidity-amend';
|
||||
import { TxDetailsLiquidityCancellation } from './tx-liquidity-cancel';
|
||||
import { TxDetailsDataSubmission } from './tx-data-submission';
|
||||
import { TxProposalVote } from './tx-proposal-vote';
|
||||
|
||||
interface TxDetailsWrapperProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@@ -44,9 +44,23 @@ export const TxDetailsWrapper = ({
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const raw = get(blockData, `result.block.data.txs[${txData.index}]`);
|
||||
|
||||
return (
|
||||
<div key={`txd-${txData.hash}`}>
|
||||
<section>{child({ txData, pubKey, blockData })}</section>
|
||||
|
||||
<details title={t('Decoded transaction')} className="mt-3">
|
||||
<summary className="cursor-pointer">{t('Decoded transaction')}</summary>
|
||||
<TxContent data={txData} />
|
||||
</details>
|
||||
|
||||
{raw ? (
|
||||
<details title={t('Raw transaction')} className="mt-3">
|
||||
<summary className="cursor-pointer">{t('Raw transaction')}</summary>
|
||||
<code className="break-all font-mono text-xs">{raw}</code>
|
||||
</details>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -68,16 +82,12 @@ function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
|
||||
switch (txData.type) {
|
||||
case 'Submit Order':
|
||||
return TxDetailsOrder;
|
||||
case 'Submit Oracle Data':
|
||||
return TxDetailsDataSubmission;
|
||||
case 'Cancel Order':
|
||||
return TxDetailsOrderCancel;
|
||||
case 'Amend Order':
|
||||
return TxDetailsOrderAmend;
|
||||
case 'Validator Heartbeat':
|
||||
return TxDetailsHeartbeat;
|
||||
case 'Vote on Proposal':
|
||||
return TxProposalVote;
|
||||
case 'Batch Market Instructions':
|
||||
return TxDetailsBatch;
|
||||
case 'Chain Event':
|
||||
|
||||
@@ -55,7 +55,6 @@ export const TxDetailsLiquidityAmendment = ({
|
||||
<PriceInMarket
|
||||
price={amendment.commitmentAmount}
|
||||
marketId={marketId}
|
||||
decimalSource="SETTLEMENT_ASSET"
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
@@ -27,7 +27,7 @@ export const TxDetailsLiquidityCancellation = ({
|
||||
pubKey,
|
||||
blockData,
|
||||
}: TxDetailsLiquidityCancellationProps) => {
|
||||
if (!txData || !txData.command.liquidityProvisionCancellation) {
|
||||
if (!txData || !txData.command.liquidityProvisionAmendment) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ export const TxDetailsLiquiditySubmission = ({
|
||||
<PriceInMarket
|
||||
price={submission.commitmentAmount}
|
||||
marketId={marketId}
|
||||
decimalSource="SETTLEMENT_ASSET"
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
@@ -6,7 +6,6 @@ import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
||||
import { txSignatureToDeterministicId } from '../lib/deterministic-ids';
|
||||
import DeterministicOrderDetails from '../../order-details/deterministic-order-details';
|
||||
import Hash from '../../links/hash';
|
||||
|
||||
interface TxDetailsOrderProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@@ -48,13 +47,7 @@ export const TxDetailsOrder = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Order')}</TableCell>
|
||||
<TableCell>
|
||||
<Hash text={deterministicId} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Market ID')}</TableCell>
|
||||
<TableCell>
|
||||
<MarketLink id={marketId} showMarketName={false} />
|
||||
<code>{deterministicId}</code>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
||||
import ProposalLink from '../../links/proposal-link/proposal-link';
|
||||
|
||||
interface TxProposalVoteProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
pubKey: string | undefined;
|
||||
blockData: TendermintBlocksResponse | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* A vote on a proposal.
|
||||
*
|
||||
* One inconsistency here that feels right but should be standardised is that there are two rows
|
||||
* for the proposal ID, one that creates a link with the text of the proposal title that takes
|
||||
* a user out to the governance site, and the other that just shows the ID. Both are useful, but
|
||||
* doesn't feel quite right. This could be fixed with a separate component to display a preview
|
||||
* of the proposal and link off to the governance site, removing the title from the header. Or
|
||||
* something else. For now, this is more useful than the default view
|
||||
*/
|
||||
export const TxProposalVote = ({
|
||||
txData,
|
||||
pubKey,
|
||||
blockData,
|
||||
}: TxProposalVoteProps) => {
|
||||
if (!txData || !txData.command.voteSubmission) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const vote = txData.command.voteSubmission.value ? '👍' : '👎';
|
||||
return (
|
||||
<TableWithTbody className="mb-8">
|
||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Proposal ID')}</TableCell>
|
||||
<TableCell>{txData.command.voteSubmission.proposalId}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Proposal details')}</TableCell>
|
||||
<TableCell>
|
||||
<ProposalLink id={txData.command.voteSubmission.proposalId} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Proposal')}</TableCell>
|
||||
<TableCell>{txData.command.voteSubmission.proposalId}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Vote')}</TableCell>
|
||||
<TableCell>{vote}</TableCell>
|
||||
</TableRow>
|
||||
</TableWithTbody>
|
||||
);
|
||||
};
|
||||
@@ -1,75 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import get from 'lodash/get';
|
||||
import { Select } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import type { BlockExplorerTransactionResult } from '../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../routes/blocks/tendermint-blocks-response';
|
||||
|
||||
export function getClassName(showTxData: ShowTxDataType) {
|
||||
const baseClasses =
|
||||
'font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]';
|
||||
if (showTxData === 'JSON') {
|
||||
return `${baseClasses} whitespace-pre overflow-x-scroll`;
|
||||
} else {
|
||||
return baseClasses;
|
||||
}
|
||||
}
|
||||
|
||||
export function getContents(
|
||||
showTxData: ShowTxDataType,
|
||||
txData: BlockExplorerTransactionResult | null,
|
||||
blockData: TendermintBlocksResponse | null | undefined
|
||||
) {
|
||||
if (showTxData === 'JSON') {
|
||||
if (txData) {
|
||||
return JSON.stringify(txData.command, undefined, 1);
|
||||
}
|
||||
} else {
|
||||
if (txData && blockData) {
|
||||
return get(blockData, `result.block.data.txs[${txData.index}]`);
|
||||
}
|
||||
}
|
||||
|
||||
return '-';
|
||||
}
|
||||
|
||||
type ShowTxDataType = 'JSON' | 'base64';
|
||||
|
||||
interface TxDataViewProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
blockData: TendermintBlocksResponse | undefined;
|
||||
}
|
||||
|
||||
export const TxDataView = ({ txData, blockData }: TxDataViewProps) => {
|
||||
const [showTxData, setShowTxData] = useState<ShowTxDataType>('JSON');
|
||||
|
||||
if (!txData) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<details title={t('Show raw transaction')}>
|
||||
<summary className="cursor-pointer">{t('Show raw transaction')}</summary>
|
||||
<div className="py-4">
|
||||
<textarea
|
||||
readOnly={true}
|
||||
className={getClassName(showTxData)}
|
||||
rows={12}
|
||||
cols={120}
|
||||
value={getContents(showTxData, txData, blockData)}
|
||||
/>
|
||||
<div className="w-40">
|
||||
<Select
|
||||
placeholder="View as..."
|
||||
onChange={(v) => setShowTxData(v.target.value as ShowTxDataType)}
|
||||
value={'JSON'}
|
||||
>
|
||||
<option value={'JSON'}>JSON</option>
|
||||
<option value={'base64'}>Base64</option>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
};
|
||||
@@ -115,7 +115,7 @@ export const TxsInfiniteList = ({
|
||||
className="List"
|
||||
height={995}
|
||||
itemCount={itemCount}
|
||||
itemSize={isStacked ? 134 : 50}
|
||||
itemSize={isStacked ? 134 : 72}
|
||||
onItemsRendered={onItemsRendered}
|
||||
ref={ref}
|
||||
width={'100%'}
|
||||
|
||||
@@ -16,7 +16,6 @@ export const ENV = {
|
||||
tendermintUrl: windowOrDefault('NX_TENDERMINT_URL'),
|
||||
tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'),
|
||||
ethExplorerUrl: windowOrDefault('NX_ETHERSCAN_URL'),
|
||||
governanceUrl: windowOrDefault('NX_VEGA_GOVERNANCE_URL'),
|
||||
},
|
||||
flags: {
|
||||
assets: truthy.includes(windowOrDefault('NX_EXPLORER_ASSETS')),
|
||||
|
||||
@@ -51,9 +51,6 @@ fragment ExplorerOracleDataSource on OracleSpec {
|
||||
|
||||
fragment ExplorerOracleDataConnection on OracleSpec {
|
||||
dataConnection {
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
}
|
||||
edges {
|
||||
node {
|
||||
externalData {
|
||||
@@ -82,21 +79,12 @@ fragment ExplorerOracleDataConnection on OracleSpec {
|
||||
}
|
||||
|
||||
query ExplorerOracleSpecs {
|
||||
oracleSpecsConnection(pagination: { first: 50 }) {
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
}
|
||||
oracleSpecsConnection {
|
||||
edges {
|
||||
node {
|
||||
...ExplorerOracleDataSource
|
||||
...ExplorerOracleDataConnection
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query ExplorerOracleSpecById($id: ID!) {
|
||||
oracleSpec(oracleSpecId: $id) {
|
||||
...ExplorerOracleDataSource
|
||||
...ExplorerOracleDataConnection
|
||||
}
|
||||
}
|
||||
|
||||
+5
-55
@@ -5,19 +5,12 @@ import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerOracleDataSourceFragment = { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } } };
|
||||
|
||||
export type ExplorerOracleDataConnectionFragment = { __typename?: 'OracleSpec', dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
||||
export type ExplorerOracleDataConnectionFragment = { __typename?: 'OracleSpec', dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
||||
|
||||
export type ExplorerOracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
|
||||
|
||||
export type ExplorerOracleSpecByIdQueryVariables = Types.Exact<{
|
||||
id: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerOracleSpecByIdQuery = { __typename?: 'Query', oracleSpec?: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } | null };
|
||||
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
|
||||
|
||||
export const ExplorerOracleDataSourceFragmentDoc = gql`
|
||||
fragment ExplorerOracleDataSource on OracleSpec {
|
||||
@@ -73,10 +66,7 @@ export const ExplorerOracleDataSourceFragmentDoc = gql`
|
||||
`;
|
||||
export const ExplorerOracleDataConnectionFragmentDoc = gql`
|
||||
fragment ExplorerOracleDataConnection on OracleSpec {
|
||||
dataConnection(pagination: {first: 1}) {
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
}
|
||||
dataConnection {
|
||||
edges {
|
||||
node {
|
||||
externalData {
|
||||
@@ -106,10 +96,7 @@ export const ExplorerOracleDataConnectionFragmentDoc = gql`
|
||||
`;
|
||||
export const ExplorerOracleSpecsDocument = gql`
|
||||
query ExplorerOracleSpecs {
|
||||
oracleSpecsConnection(pagination: {first: 50}) {
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
}
|
||||
oracleSpecsConnection {
|
||||
edges {
|
||||
node {
|
||||
...ExplorerOracleDataSource
|
||||
@@ -146,41 +133,4 @@ export function useExplorerOracleSpecsLazyQuery(baseOptions?: Apollo.LazyQueryHo
|
||||
}
|
||||
export type ExplorerOracleSpecsQueryHookResult = ReturnType<typeof useExplorerOracleSpecsQuery>;
|
||||
export type ExplorerOracleSpecsLazyQueryHookResult = ReturnType<typeof useExplorerOracleSpecsLazyQuery>;
|
||||
export type ExplorerOracleSpecsQueryResult = Apollo.QueryResult<ExplorerOracleSpecsQuery, ExplorerOracleSpecsQueryVariables>;
|
||||
export const ExplorerOracleSpecByIdDocument = gql`
|
||||
query ExplorerOracleSpecById($id: ID!) {
|
||||
oracleSpec(oracleSpecId: $id) {
|
||||
...ExplorerOracleDataSource
|
||||
...ExplorerOracleDataConnection
|
||||
}
|
||||
}
|
||||
${ExplorerOracleDataSourceFragmentDoc}
|
||||
${ExplorerOracleDataConnectionFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useExplorerOracleSpecByIdQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useExplorerOracleSpecByIdQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useExplorerOracleSpecByIdQuery` 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 } = useExplorerOracleSpecByIdQuery({
|
||||
* variables: {
|
||||
* id: // value for 'id'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useExplorerOracleSpecByIdQuery(baseOptions: Apollo.QueryHookOptions<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>(ExplorerOracleSpecByIdDocument, options);
|
||||
}
|
||||
export function useExplorerOracleSpecByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>(ExplorerOracleSpecByIdDocument, options);
|
||||
}
|
||||
export type ExplorerOracleSpecByIdQueryHookResult = ReturnType<typeof useExplorerOracleSpecByIdQuery>;
|
||||
export type ExplorerOracleSpecByIdLazyQueryHookResult = ReturnType<typeof useExplorerOracleSpecByIdLazyQuery>;
|
||||
export type ExplorerOracleSpecByIdQueryResult = Apollo.QueryResult<ExplorerOracleSpecByIdQuery, ExplorerOracleSpecByIdQueryVariables>;
|
||||
export type ExplorerOracleSpecsQueryResult = Apollo.QueryResult<ExplorerOracleSpecsQuery, ExplorerOracleSpecsQueryVariables>;
|
||||
@@ -37,7 +37,7 @@ describe('Oracle Data view', () => {
|
||||
dataConnection: {
|
||||
edges: [],
|
||||
},
|
||||
} as unknown as ExplorerOracleDataConnectionFragment)
|
||||
} as ExplorerOracleDataConnectionFragment)
|
||||
);
|
||||
expect(res.container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ describe('Oracle Signers component', () => {
|
||||
__typename: 'Signer',
|
||||
signer: {
|
||||
__typename: 'PubKey',
|
||||
key: '1234567891234567789123456789123456778912345678912345677891234567',
|
||||
key: '123',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../components/links/eth-explorer-link/eth-explorer-link';
|
||||
import { TableRow, TableCell, TableHeader } from '../../../components/table';
|
||||
import { remove0x } from '@vegaprotocol/react-helpers';
|
||||
|
||||
import type { SourceType } from './oracle';
|
||||
|
||||
@@ -15,15 +14,7 @@ export type Signer = {
|
||||
};
|
||||
|
||||
export function getAddressTypeLabel(signer: Signer) {
|
||||
const res = signer.__typename === 'ETHAddress' ? 'ETH' : 'Vega';
|
||||
|
||||
// This is a hack: some older oracles were submitted before proper checks stopped
|
||||
// ETH addresses being returned as Vega addresses
|
||||
if (res === 'Vega' && signer?.key?.length !== 64) {
|
||||
return 'ETH';
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
return signer.__typename === 'ETHAddress' ? 'ETH' : 'Vega';
|
||||
}
|
||||
|
||||
export function getAddress(signer: Signer) {
|
||||
@@ -38,16 +29,6 @@ export function getAddressLink(signer: Signer) {
|
||||
|
||||
if (signer.__typename === 'ETHAddress') {
|
||||
return <EthExplorerLink id={address} type={EthExplorerLinkTypes.address} />;
|
||||
} else if (signer.__typename === 'PubKey' && address.length !== 64) {
|
||||
// This is a hack: some older oracles were submitted before proper checks stopped
|
||||
// ETH addresses being returned as Vega addresses
|
||||
// Hacky 0x prefixing as a bonus
|
||||
return (
|
||||
<EthExplorerLink
|
||||
id={`0x${remove0x(address)}`}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
);
|
||||
} else if (signer.__typename === 'PubKey') {
|
||||
return <PartyLink id={address} />;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ import { OracleData } from './oracle-data';
|
||||
import { OracleFilter } from './oracle-filter';
|
||||
import { OracleDetailsType } from './oracle-details-type';
|
||||
import { OracleMarkets } from './oracle-markets';
|
||||
import { OracleSigners } from './oracle-signers';
|
||||
import OracleLink from '../../../components/links/oracle-link/oracle-link';
|
||||
|
||||
export type SourceType =
|
||||
ExplorerOracleDataSourceFragment['dataSourceSpec']['spec']['data']['sourceType'];
|
||||
@@ -23,47 +21,36 @@ interface OracleDetailsProps {
|
||||
id: string;
|
||||
dataSource: ExplorerOracleDataSourceFragment;
|
||||
dataConnection: ExplorerOracleDataConnectionFragment;
|
||||
// Defaults to false. Hides the count of 'broadcasts' this oracle has seen
|
||||
showBroadcasts?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes:
|
||||
* - Matched data is really 'Data that matched this oracle' and given oracles are unique
|
||||
* to each market, and each serves either as trading termination or settlement, really
|
||||
* they will only ever see 1 match (most likely). So it should be more like 'Has seen
|
||||
* data' vs 'Has not yet seen data'
|
||||
*/
|
||||
export const OracleDetails = ({
|
||||
id,
|
||||
dataSource,
|
||||
dataConnection,
|
||||
showBroadcasts = false,
|
||||
}: OracleDetailsProps) => {
|
||||
const sourceType = dataSource.dataSourceSpec.spec.data.sourceType;
|
||||
const reportsCount: number = dataConnection.dataConnection.edges?.length || 0;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<TableWithTbody className="mb-2">
|
||||
<TableWithTbody>
|
||||
<TableRow modifier="bordered">
|
||||
<TableHeader scope="row">{t('ID')}</TableHeader>
|
||||
<TableCell modifier="bordered">
|
||||
<OracleLink id={id} />
|
||||
</TableCell>
|
||||
<TableCell modifier="bordered">{id}</TableCell>
|
||||
</TableRow>
|
||||
<OracleDetailsType type={sourceType.__typename} />
|
||||
<OracleSigners sourceType={sourceType} />
|
||||
{
|
||||
// Disabled until https://github.com/vegaprotocol/vega/issues/7286 is released
|
||||
/*<OracleSigners sourceType={sourceType} />*/
|
||||
}
|
||||
<OracleMarkets id={id} />
|
||||
<TableRow modifier="bordered">
|
||||
<TableHeader scope="row">{t('Matched data')}</TableHeader>
|
||||
<TableCell modifier="bordered">
|
||||
{showBroadcasts ? reportsCount : reportsCount > 0 ? '✅' : '❌'}
|
||||
</TableCell>
|
||||
<TableHeader scope="row">{t('Broadcasts')}</TableHeader>
|
||||
<TableCell modifier="bordered">{reportsCount}</TableCell>
|
||||
</TableRow>
|
||||
</TableWithTbody>
|
||||
<OracleFilter data={dataSource} />
|
||||
{showBroadcasts ? <OracleData data={dataConnection} /> : null}
|
||||
<OracleData data={dataConnection} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { RouteTitle } from '../../../components/route-title';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { useExplorerOracleSpecsQuery } from '../__generated__/Oracles';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
import { OracleDetails } from '../components/oracle';
|
||||
import { useScrollToLocation } from '../../../hooks/scroll-to-location';
|
||||
import filter from 'recursive-key-filter';
|
||||
|
||||
const Oracles = () => {
|
||||
const { data, loading } = useExplorerOracleSpecsQuery();
|
||||
|
||||
useDocumentTitle(['Oracles']);
|
||||
useScrollToLocation();
|
||||
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle data-testid="oracle-specs-heading">{t('Oracles')}</RouteTitle>
|
||||
{loading ? <Loader /> : null}
|
||||
{data?.oracleSpecsConnection?.edges
|
||||
? data.oracleSpecsConnection.edges.map((o) => {
|
||||
const id = o?.node.dataSourceSpec.spec.id;
|
||||
if (!id) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div id={id} key={id} className="mb-10">
|
||||
<OracleDetails
|
||||
id={id}
|
||||
dataSource={o?.node}
|
||||
dataConnection={o?.node}
|
||||
/>
|
||||
<details>
|
||||
<summary className="pointer">JSON</summary>
|
||||
<SyntaxHighlighter data={filter(o, ['__typename'])} />
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
: null}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Oracles;
|
||||
@@ -1,49 +0,0 @@
|
||||
import { RouteTitle } from '../../../components/route-title';
|
||||
import { RenderFetched } from '../../../components/render-fetched';
|
||||
import { t, truncateByChars } from '@vegaprotocol/react-helpers';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useExplorerOracleSpecByIdQuery } from '../__generated__/Oracles';
|
||||
import { OracleDetails } from '../components/oracle';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import filter from 'recursive-key-filter';
|
||||
import { TruncateInline } from '../../../components/truncate/truncate';
|
||||
|
||||
export const Oracle = () => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
useDocumentTitle(['Oracle', `Oracle #${truncateByChars(id || '1', 5, 5)}`]);
|
||||
|
||||
const { data, error, loading } = useExplorerOracleSpecByIdQuery({
|
||||
variables: {
|
||||
id: id || '1',
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle data-testid="block-header">
|
||||
{t(`Oracle `)}
|
||||
<TruncateInline startChars={5} endChars={5} text={id || '1'} />
|
||||
</RouteTitle>
|
||||
<RenderFetched error={error} loading={loading}>
|
||||
{data?.oracleSpec ? (
|
||||
<div id={id} key={id} className="mb-10">
|
||||
<OracleDetails
|
||||
id={id || ''}
|
||||
dataSource={data?.oracleSpec}
|
||||
dataConnection={data?.oracleSpec}
|
||||
showBroadcasts={true}
|
||||
/>
|
||||
<details>
|
||||
<summary className="pointer">JSON</summary>
|
||||
<SyntaxHighlighter data={filter(data, ['__typename'])} />
|
||||
</details>
|
||||
</div>
|
||||
) : (
|
||||
<span></span>
|
||||
)}
|
||||
</RenderFetched>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,45 @@
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { useExplorerOracleSpecsQuery } from './__generated__/Oracles';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
import { OracleDetails } from './components/oracle';
|
||||
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
||||
import filter from 'recursive-key-filter';
|
||||
|
||||
const OraclePage = () => {
|
||||
return <Outlet />;
|
||||
const Oracles = () => {
|
||||
const { data, loading } = useExplorerOracleSpecsQuery();
|
||||
|
||||
useDocumentTitle(['Oracles']);
|
||||
useScrollToLocation();
|
||||
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle data-testid="oracle-specs-heading">{t('Oracles')}</RouteTitle>
|
||||
{loading ? <Loader /> : null}
|
||||
{data?.oracleSpecsConnection?.edges
|
||||
? data.oracleSpecsConnection.edges.map((o) => {
|
||||
const id = o?.node.dataSourceSpec.spec.id;
|
||||
if (!id) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div id={id} key={id} className="mb-10 cursor-pointer">
|
||||
<OracleDetails
|
||||
id={id}
|
||||
dataSource={o?.node}
|
||||
dataConnection={o?.node}
|
||||
/>
|
||||
<details>
|
||||
<summary className="pointer">JSON</summary>
|
||||
<SyntaxHighlighter data={filter(o, ['__typename'])} />
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
: null}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default OraclePage;
|
||||
export default Oracles;
|
||||
|
||||
@@ -3,9 +3,7 @@ import BlockPage from './blocks';
|
||||
import Governance from './governance';
|
||||
import Home from './home';
|
||||
import Markets from './markets';
|
||||
import OraclePage from './oracles';
|
||||
import Oracles from './oracles/home';
|
||||
import { Oracle } from './oracles/id';
|
||||
import Oracles from './oracles';
|
||||
import Party from './parties';
|
||||
import { Parties } from './parties/home';
|
||||
import { Party as PartySingle } from './parties/id';
|
||||
@@ -87,6 +85,17 @@ const marketsRoutes = flags.markets
|
||||
]
|
||||
: [];
|
||||
|
||||
const oraclesRoutes = flags.oracles
|
||||
? [
|
||||
{
|
||||
path: Routes.ORACLES,
|
||||
name: 'Oracles',
|
||||
text: t('Oracles'),
|
||||
element: <Oracles />,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const networkParametersRoutes = flags.networkParameters
|
||||
? [
|
||||
{
|
||||
@@ -152,27 +161,12 @@ const routerConfig = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.ORACLES,
|
||||
name: 'Oracles',
|
||||
text: t('Oracles'),
|
||||
element: <OraclePage />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Oracles />,
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
element: <Oracle />,
|
||||
},
|
||||
],
|
||||
},
|
||||
...partiesRoutes,
|
||||
...assetsRoutes,
|
||||
...genesisRoutes,
|
||||
...governanceRoutes,
|
||||
...marketsRoutes,
|
||||
...oraclesRoutes,
|
||||
...networkParametersRoutes,
|
||||
...validators,
|
||||
];
|
||||
|
||||
+10
-13
@@ -10,6 +10,7 @@ import {
|
||||
formatNumberPercentage,
|
||||
t,
|
||||
toBigNum,
|
||||
getDateTimeFormat,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
|
||||
import type * as Schema from '@vegaprotocol/types';
|
||||
@@ -30,7 +31,6 @@ import { HealthBar } from '../../health-bar';
|
||||
import { HealthDialog } from '../../health-dialog';
|
||||
import { Status } from '../../status';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { getExpiryDate } from '@vegaprotocol/react-helpers';
|
||||
|
||||
export const MarketList = () => {
|
||||
const { data, error, loading } = useMarketsLiquidity();
|
||||
@@ -299,20 +299,17 @@ export const MarketList = () => {
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Closing Time')}
|
||||
field="tradableInstrument.instrument.metadata.tags"
|
||||
field="proposal.terms.closingDatetime"
|
||||
headerTooltip={t('Closing time of the market')}
|
||||
valueFormatter={({
|
||||
data,
|
||||
}: VegaValueFormatterParams<Market, ''>) => {
|
||||
let expiry;
|
||||
if (data?.tradableInstrument.instrument.metadata.tags) {
|
||||
expiry = getExpiryDate(
|
||||
data?.tradableInstrument.instrument.metadata.tags,
|
||||
data?.marketTimestamps.close,
|
||||
data?.state
|
||||
);
|
||||
}
|
||||
return expiry ? expiry : '-';
|
||||
value,
|
||||
}: VegaValueFormatterParams<
|
||||
Market,
|
||||
'proposal.terms.closingDatetime'
|
||||
>) => {
|
||||
return value
|
||||
? getDateTimeFormat().format(new Date(value).getTime())
|
||||
: '-';
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,6 @@ NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
|
||||
#Test configuration variables
|
||||
CYPRESS_FAIRGROUND=false
|
||||
|
||||
@@ -14,7 +14,6 @@ NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit suppl
|
||||
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
|
||||
#Test configuration variables
|
||||
CYPRESS_FAIRGROUND=false
|
||||
|
||||
@@ -8,4 +8,3 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
|
||||
@@ -8,5 +8,4 @@ NX_ETHERSCAN_URL=https://etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
|
||||
@@ -8,4 +8,3 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_EXPLORER_URL=https://mirror.explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
|
||||
@@ -5,4 +5,3 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://sta
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
|
||||
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
|
||||
@@ -5,4 +5,3 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://sta
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
|
||||
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
|
||||
@@ -6,4 +6,3 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
|
||||
@@ -9,4 +9,3 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
|
||||
@@ -7,13 +7,13 @@ fragment WalletDelegationFields on Delegation {
|
||||
epoch
|
||||
}
|
||||
|
||||
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
query Delegations($partyId: ID!) {
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
...WalletDelegationFields
|
||||
|
||||
@@ -7,7 +7,6 @@ export type WalletDelegationFieldsFragment = { __typename?: 'Delegation', amount
|
||||
|
||||
export type DelegationsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
|
||||
}>;
|
||||
|
||||
|
||||
@@ -24,13 +23,13 @@ export const WalletDelegationFieldsFragmentDoc = gql`
|
||||
}
|
||||
`;
|
||||
export const DelegationsDocument = gql`
|
||||
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
query Delegations($partyId: ID!) {
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
...WalletDelegationFields
|
||||
@@ -77,7 +76,6 @@ export const DelegationsDocument = gql`
|
||||
* const { data, loading, error } = useDelegationsQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* delegationsPagination: // value for 'delegationsPagination'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
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 DelegationsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
epoch
|
||||
}
|
||||
`;
|
||||
export const DelegationsDocument = gql`
|
||||
query Delegations($partyId: ID!) {
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
...WalletDelegationFields
|
||||
}
|
||||
}
|
||||
}
|
||||
stakingSummary {
|
||||
currentStakeAvailable
|
||||
}
|
||||
accountsConnection {
|
||||
edges {
|
||||
node {
|
||||
asset {
|
||||
name
|
||||
id
|
||||
decimals
|
||||
symbol
|
||||
source {
|
||||
__typename
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
type
|
||||
balance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${WalletDelegationFieldsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useDelegationsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useDelegationsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useDelegationsQuery` 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 } = useDelegationsQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
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>;
|
||||
@@ -4,7 +4,6 @@ import keyBy from 'lodash/keyBy';
|
||||
import uniq from 'lodash/uniq';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ENV } from '../../config';
|
||||
|
||||
import noIcon from '../../images/token-no-icon.png';
|
||||
import vegaBlack from '../../images/vega_black.png';
|
||||
@@ -24,18 +23,18 @@ import type {
|
||||
DelegationsQuery,
|
||||
DelegationsQueryVariables,
|
||||
WalletDelegationFieldsFragment,
|
||||
} from './__generated__/Delegations';
|
||||
import { DelegationsDocument } from './__generated__/Delegations';
|
||||
} from './__generated___/Delegations';
|
||||
import { DelegationsDocument } from './__generated___/Delegations';
|
||||
|
||||
export const usePollForDelegations = () => {
|
||||
const { token: vegaToken } = useContracts();
|
||||
const {
|
||||
appState: { decimals },
|
||||
} = useAppState();
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const client = useApolloClient();
|
||||
const { delegationsPagination } = ENV;
|
||||
const [delegations, setDelegations] = React.useState<
|
||||
WalletDelegationFieldsFragment[]
|
||||
>([]);
|
||||
@@ -63,14 +62,7 @@ export const usePollForDelegations = () => {
|
||||
client
|
||||
.query<DelegationsQuery, DelegationsQueryVariables>({
|
||||
query: DelegationsDocument,
|
||||
variables: {
|
||||
partyId: pubKey,
|
||||
delegationsPagination: delegationsPagination
|
||||
? {
|
||||
first: Number(delegationsPagination),
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
variables: { partyId: pubKey },
|
||||
fetchPolicy: 'network-only',
|
||||
})
|
||||
.then((res) => {
|
||||
@@ -215,7 +207,7 @@ export const usePollForDelegations = () => {
|
||||
clearInterval(interval);
|
||||
mounted = false;
|
||||
};
|
||||
}, [delegationsPagination, client, decimals, pubKey, t, vegaToken.address]);
|
||||
}, [client, decimals, pubKey, t, vegaToken.address]);
|
||||
|
||||
return { delegations, currentStakeAvailable, delegatedNodes, accounts };
|
||||
};
|
||||
|
||||
@@ -64,7 +64,6 @@ export const ENV = {
|
||||
docsUrl: windowOrDefault('NX_VEGA_DOCS_URL'),
|
||||
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
|
||||
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
|
||||
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
|
||||
flags: {
|
||||
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
|
||||
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { create } from 'zustand';
|
||||
import create from 'zustand';
|
||||
import type { UserTrancheBalance } from '../../contexts/app-state/app-state-context';
|
||||
|
||||
export interface AssociationBreakdown {
|
||||
|
||||
@@ -20,24 +20,6 @@ query Proposal($proposalId: ID!) {
|
||||
... on NewMarket {
|
||||
decimalPlaces
|
||||
metadata
|
||||
lpPriceRange
|
||||
riskParameters {
|
||||
... on LogNormalRiskModel {
|
||||
riskAversionParameter
|
||||
tau
|
||||
params {
|
||||
mu
|
||||
r
|
||||
sigma
|
||||
}
|
||||
}
|
||||
... on SimpleRiskModel {
|
||||
params {
|
||||
factorLong
|
||||
factorShort
|
||||
}
|
||||
}
|
||||
}
|
||||
instrument {
|
||||
name
|
||||
code
|
||||
@@ -50,7 +32,6 @@ query Proposal($proposalId: ID!) {
|
||||
quantum
|
||||
}
|
||||
quoteName
|
||||
|
||||
dataSourceSpecForSettlementData {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionInternal {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -20,7 +20,7 @@ fragment DelegationFields on Delegation {
|
||||
epoch
|
||||
}
|
||||
|
||||
query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
query Rewards($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
rewardsConnection {
|
||||
@@ -30,7 +30,7 @@ query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
}
|
||||
}
|
||||
}
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
...DelegationFields
|
||||
|
||||
+2
-4
@@ -9,7 +9,6 @@ export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: stri
|
||||
|
||||
export type RewardsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
|
||||
}>;
|
||||
|
||||
|
||||
@@ -40,7 +39,7 @@ export const DelegationFieldsFragmentDoc = gql`
|
||||
}
|
||||
`;
|
||||
export const RewardsDocument = gql`
|
||||
query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
query Rewards($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
rewardsConnection {
|
||||
@@ -50,7 +49,7 @@ export const RewardsDocument = gql`
|
||||
}
|
||||
}
|
||||
}
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
...DelegationFields
|
||||
@@ -83,7 +82,6 @@ ${DelegationFieldsFragmentDoc}`;
|
||||
* const { data, loading, error } = useRewardsQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* delegationsPagination: // value for 'delegationsPagination'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type RewardFieldsFragment = { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } };
|
||||
|
||||
export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number };
|
||||
|
||||
export type RewardsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type RewardsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, rewardsConnection?: { __typename?: 'RewardsConnection', edges?: Array<{ __typename?: 'RewardEdge', node: { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } } } | null> | null } | null, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } } };
|
||||
|
||||
export const RewardFieldsFragmentDoc = gql`
|
||||
fragment RewardFields on Reward {
|
||||
rewardType
|
||||
asset {
|
||||
id
|
||||
symbol
|
||||
}
|
||||
party {
|
||||
id
|
||||
}
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
amount
|
||||
percentageOfTotal
|
||||
receivedAt
|
||||
}
|
||||
`;
|
||||
export const DelegationFieldsFragmentDoc = gql`
|
||||
fragment DelegationFields on Delegation {
|
||||
amount
|
||||
epoch
|
||||
}
|
||||
`;
|
||||
export const RewardsDocument = gql`
|
||||
query Rewards($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
rewardsConnection {
|
||||
edges {
|
||||
node {
|
||||
...RewardFields
|
||||
}
|
||||
}
|
||||
}
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
...DelegationFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
epoch {
|
||||
id
|
||||
timestamps {
|
||||
start
|
||||
end
|
||||
expiry
|
||||
}
|
||||
}
|
||||
}
|
||||
${RewardFieldsFragmentDoc}
|
||||
${DelegationFieldsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useRewardsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useRewardsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useRewardsQuery` 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 } = useRewardsQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useRewardsQuery(baseOptions: Apollo.QueryHookOptions<RewardsQuery, RewardsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<RewardsQuery, RewardsQueryVariables>(RewardsDocument, options);
|
||||
}
|
||||
export function useRewardsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<RewardsQuery, RewardsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<RewardsQuery, RewardsQueryVariables>(RewardsDocument, options);
|
||||
}
|
||||
export type RewardsQueryHookResult = ReturnType<typeof useRewardsQuery>;
|
||||
export type RewardsLazyQueryHookResult = ReturnType<typeof useRewardsLazyQuery>;
|
||||
export type RewardsQueryResult = Apollo.QueryResult<RewardsQuery, RewardsQueryVariables>;
|
||||
@@ -9,7 +9,7 @@ import type {
|
||||
RewardsQuery,
|
||||
RewardFieldsFragment,
|
||||
DelegationFieldsFragment,
|
||||
} from './__generated__/Rewards';
|
||||
} from './__generated___/Rewards';
|
||||
import {
|
||||
formatNumber,
|
||||
removePaginationWrapper,
|
||||
|
||||
@@ -4,7 +4,6 @@ import { formatDistance } from 'date-fns';
|
||||
import Duration from 'duration-js';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ENV } from '../../../config';
|
||||
|
||||
import { EpochCountdown } from '../../../components/epoch-countdown';
|
||||
import { Heading } from '../../../components/heading';
|
||||
@@ -16,7 +15,7 @@ import {
|
||||
import { RewardInfo } from './reward-info';
|
||||
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||
import { useNetworkParams, NetworkParams } from '@vegaprotocol/react-helpers';
|
||||
import { useRewardsQuery } from './__generated__/Rewards';
|
||||
import { useRewardsQuery } from './__generated___/Rewards';
|
||||
|
||||
export const RewardsPage = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -25,16 +24,8 @@ export const RewardsPage = () => {
|
||||
openVegaWalletDialog: store.openVegaWalletDialog,
|
||||
}));
|
||||
const { appDispatch } = useAppState();
|
||||
const { delegationsPagination } = ENV;
|
||||
const { data, loading, error } = useRewardsQuery({
|
||||
variables: {
|
||||
partyId: pubKey || '',
|
||||
delegationsPagination: delegationsPagination
|
||||
? {
|
||||
first: Number(delegationsPagination),
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
const { params } = useNetworkParams([
|
||||
|
||||
@@ -6,10 +6,10 @@ fragment StakingDelegationsFields on Delegation {
|
||||
epoch
|
||||
}
|
||||
|
||||
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
query PartyDelegations($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
...StakingDelegationsFields
|
||||
|
||||
@@ -23,13 +23,13 @@ fragment StakingNodeFields on Node {
|
||||
}
|
||||
}
|
||||
|
||||
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
query Staking($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
stakingSummary {
|
||||
currentStakeAvailable
|
||||
}
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
amount
|
||||
|
||||
@@ -7,7 +7,6 @@ export type StakingDelegationsFieldsFragment = { __typename?: 'Delegation', amou
|
||||
|
||||
export type PartyDelegationsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
|
||||
}>;
|
||||
|
||||
|
||||
@@ -23,10 +22,10 @@ export const StakingDelegationsFieldsFragmentDoc = gql`
|
||||
}
|
||||
`;
|
||||
export const PartyDelegationsDocument = gql`
|
||||
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
query PartyDelegations($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
...StakingDelegationsFields
|
||||
@@ -53,7 +52,6 @@ export const PartyDelegationsDocument = gql`
|
||||
* const { data, loading, error } = usePartyDelegationsQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* delegationsPagination: // value for 'delegationsPagination'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
|
||||
+2
-4
@@ -7,7 +7,6 @@ export type StakingNodeFieldsFragment = { __typename?: 'Node', id: string, name:
|
||||
|
||||
export type StakingQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
|
||||
}>;
|
||||
|
||||
|
||||
@@ -40,13 +39,13 @@ export const StakingNodeFieldsFragmentDoc = gql`
|
||||
}
|
||||
`;
|
||||
export const StakingDocument = gql`
|
||||
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
query Staking($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
stakingSummary {
|
||||
currentStakeAvailable
|
||||
}
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
amount
|
||||
@@ -95,7 +94,6 @@ export const StakingDocument = gql`
|
||||
* const { data, loading, error } = useStakingQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* delegationsPagination: // value for 'delegationsPagination'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
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 PartyDelegationsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
epoch
|
||||
}
|
||||
`;
|
||||
export const PartyDelegationsDocument = gql`
|
||||
query PartyDelegations($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection {
|
||||
edges {
|
||||
node {
|
||||
...StakingDelegationsFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
}
|
||||
${StakingDelegationsFieldsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __usePartyDelegationsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `usePartyDelegationsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `usePartyDelegationsQuery` 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 } = usePartyDelegationsQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
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>;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user