Merge branch 'master' into feat/40-tx-styling

This commit is contained in:
Sam Keen 2022-03-18 14:55:43 +00:00 committed by GitHub
commit 514b30bebd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
135 changed files with 4159 additions and 626 deletions

3
.gitignore vendored
View File

@ -37,3 +37,6 @@ testem.log
# System Files # System Files
.DS_Store .DS_Store
Thumbs.db Thumbs.db
.local.env
.env.local

View File

@ -2,3 +2,4 @@
/dist /dist
/coverage /coverage
__generated__

View File

@ -1,5 +1,5 @@
{ {
"baseUrl": "http://localhost:4200", "baseUrl": "http://localhost:3000",
"projectId": "et4snf", "projectId": "et4snf",
"fileServerFolder": ".", "fileServerFolder": ".",
"fixturesFolder": false, "fixturesFolder": false,

View File

@ -40,6 +40,7 @@
"serve": { "serve": {
"executor": "@nrwl/web:dev-server", "executor": "@nrwl/web:dev-server",
"options": { "options": {
"port": 3000,
"buildTarget": "explorer:build", "buildTarget": "explorer:build",
"hmr": true "hmr": true
}, },
@ -65,16 +66,6 @@
"passWithNoTests": true "passWithNoTests": true
} }
}, },
"generate": {
"builder": "@nrwl/workspace:run-commands",
"options": {
"commands": [
{
"command": "npx apollo codegen:generate --config=apps/explorer/apollo.config.js --target=typescript --globalTypesFile=apps/explorer/src/__generated__/globalTypes.ts"
}
]
}
},
"build-netlify": { "build-netlify": {
"builder": "@nrwl/workspace:run-commands", "builder": "@nrwl/workspace:run-commands",
"options": { "options": {

View File

@ -11,92 +11,92 @@
* The various account types we have (used by collateral) * The various account types we have (used by collateral)
*/ */
export enum AccountType { export enum AccountType {
Bond = 'Bond', Bond = "Bond",
FeeInfrastructure = 'FeeInfrastructure', FeeInfrastructure = "FeeInfrastructure",
FeeLiquidity = 'FeeLiquidity', FeeLiquidity = "FeeLiquidity",
General = 'General', General = "General",
GlobalInsurance = 'GlobalInsurance', GlobalInsurance = "GlobalInsurance",
Insurance = 'Insurance', Insurance = "Insurance",
LockWithdraw = 'LockWithdraw', LockWithdraw = "LockWithdraw",
Margin = 'Margin', Margin = "Margin",
Settlement = 'Settlement', Settlement = "Settlement",
} }
export enum AuctionTrigger { export enum AuctionTrigger {
Batch = 'Batch', Batch = "Batch",
Liquidity = 'Liquidity', Liquidity = "Liquidity",
Opening = 'Opening', Opening = "Opening",
Price = 'Price', Price = "Price",
Unspecified = 'Unspecified', Unspecified = "Unspecified",
} }
/** /**
* The current state of a market * The current state of a market
*/ */
export enum MarketState { export enum MarketState {
Active = 'Active', Active = "Active",
Cancelled = 'Cancelled', Cancelled = "Cancelled",
Closed = 'Closed', Closed = "Closed",
Pending = 'Pending', Pending = "Pending",
Proposed = 'Proposed', Proposed = "Proposed",
Rejected = 'Rejected', Rejected = "Rejected",
Settled = 'Settled', Settled = "Settled",
Suspended = 'Suspended', Suspended = "Suspended",
TradingTerminated = 'TradingTerminated', TradingTerminated = "TradingTerminated",
} }
/** /**
* What market trading mode are we in * What market trading mode are we in
*/ */
export enum MarketTradingMode { export enum MarketTradingMode {
BatchAuction = 'BatchAuction', BatchAuction = "BatchAuction",
Continuous = 'Continuous', Continuous = "Continuous",
MonitoringAuction = 'MonitoringAuction', MonitoringAuction = "MonitoringAuction",
OpeningAuction = 'OpeningAuction', OpeningAuction = "OpeningAuction",
} }
export enum NodeStatus { export enum NodeStatus {
NonValidator = 'NonValidator', NonValidator = "NonValidator",
Validator = 'Validator', Validator = "Validator",
} }
/** /**
* Reason for the proposal being rejected by the core node * Reason for the proposal being rejected by the core node
*/ */
export enum ProposalRejectionReason { export enum ProposalRejectionReason {
CloseTimeTooLate = 'CloseTimeTooLate', CloseTimeTooLate = "CloseTimeTooLate",
CloseTimeTooSoon = 'CloseTimeTooSoon', CloseTimeTooSoon = "CloseTimeTooSoon",
CouldNotInstantiateMarket = 'CouldNotInstantiateMarket', CouldNotInstantiateMarket = "CouldNotInstantiateMarket",
EnactTimeTooLate = 'EnactTimeTooLate', EnactTimeTooLate = "EnactTimeTooLate",
EnactTimeTooSoon = 'EnactTimeTooSoon', EnactTimeTooSoon = "EnactTimeTooSoon",
IncompatibleTimestamps = 'IncompatibleTimestamps', IncompatibleTimestamps = "IncompatibleTimestamps",
InsufficientTokens = 'InsufficientTokens', InsufficientTokens = "InsufficientTokens",
InvalidAsset = 'InvalidAsset', InvalidAsset = "InvalidAsset",
InvalidAssetDetails = 'InvalidAssetDetails', InvalidAssetDetails = "InvalidAssetDetails",
InvalidFeeAmount = 'InvalidFeeAmount', InvalidFeeAmount = "InvalidFeeAmount",
InvalidFutureMaturityTimestamp = 'InvalidFutureMaturityTimestamp', InvalidFutureMaturityTimestamp = "InvalidFutureMaturityTimestamp",
InvalidFutureProduct = 'InvalidFutureProduct', InvalidFutureProduct = "InvalidFutureProduct",
InvalidInstrumentSecurity = 'InvalidInstrumentSecurity', InvalidInstrumentSecurity = "InvalidInstrumentSecurity",
InvalidRiskParameter = 'InvalidRiskParameter', InvalidRiskParameter = "InvalidRiskParameter",
InvalidShape = 'InvalidShape', InvalidShape = "InvalidShape",
MajorityThresholdNotReached = 'MajorityThresholdNotReached', MajorityThresholdNotReached = "MajorityThresholdNotReached",
MarketMissingLiquidityCommitment = 'MarketMissingLiquidityCommitment', MarketMissingLiquidityCommitment = "MarketMissingLiquidityCommitment",
MissingBuiltinAssetField = 'MissingBuiltinAssetField', MissingBuiltinAssetField = "MissingBuiltinAssetField",
MissingCommitmentAmount = 'MissingCommitmentAmount', MissingCommitmentAmount = "MissingCommitmentAmount",
MissingERC20ContractAddress = 'MissingERC20ContractAddress', MissingERC20ContractAddress = "MissingERC20ContractAddress",
NetworkParameterInvalidKey = 'NetworkParameterInvalidKey', NetworkParameterInvalidKey = "NetworkParameterInvalidKey",
NetworkParameterInvalidValue = 'NetworkParameterInvalidValue', NetworkParameterInvalidValue = "NetworkParameterInvalidValue",
NetworkParameterValidationFailed = 'NetworkParameterValidationFailed', NetworkParameterValidationFailed = "NetworkParameterValidationFailed",
NoProduct = 'NoProduct', NoProduct = "NoProduct",
NoRiskParameters = 'NoRiskParameters', NoRiskParameters = "NoRiskParameters",
NoTradingMode = 'NoTradingMode', NoTradingMode = "NoTradingMode",
NodeValidationFailed = 'NodeValidationFailed', NodeValidationFailed = "NodeValidationFailed",
OpeningAuctionDurationTooLarge = 'OpeningAuctionDurationTooLarge', OpeningAuctionDurationTooLarge = "OpeningAuctionDurationTooLarge",
OpeningAuctionDurationTooSmall = 'OpeningAuctionDurationTooSmall', OpeningAuctionDurationTooSmall = "OpeningAuctionDurationTooSmall",
ParticipationThresholdNotReached = 'ParticipationThresholdNotReached', ParticipationThresholdNotReached = "ParticipationThresholdNotReached",
ProductMaturityIsPassed = 'ProductMaturityIsPassed', ProductMaturityIsPassed = "ProductMaturityIsPassed",
UnsupportedProduct = 'UnsupportedProduct', UnsupportedProduct = "UnsupportedProduct",
UnsupportedTradingMode = 'UnsupportedTradingMode', UnsupportedTradingMode = "UnsupportedTradingMode",
} }
/** /**
@ -107,18 +107,18 @@ export enum ProposalRejectionReason {
* Proposal can enter Failed state from any other state. * Proposal can enter Failed state from any other state.
*/ */
export enum ProposalState { export enum ProposalState {
Declined = 'Declined', Declined = "Declined",
Enacted = 'Enacted', Enacted = "Enacted",
Failed = 'Failed', Failed = "Failed",
Open = 'Open', Open = "Open",
Passed = 'Passed', Passed = "Passed",
Rejected = 'Rejected', Rejected = "Rejected",
WaitingForNodeVote = 'WaitingForNodeVote', WaitingForNodeVote = "WaitingForNodeVote",
} }
export enum VoteValue { export enum VoteValue {
No = 'No', No = "No",
Yes = 'Yes', Yes = "Yes",
} }
//============================================================== //==============================================================

View File

@ -1,126 +0,0 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
//==============================================================
// START Enums and Input Objects
//==============================================================
/**
* The various account types we have (used by collateral)
*/
export enum AccountType {
Bond = "Bond",
FeeInfrastructure = "FeeInfrastructure",
FeeLiquidity = "FeeLiquidity",
General = "General",
GlobalInsurance = "GlobalInsurance",
Insurance = "Insurance",
LockWithdraw = "LockWithdraw",
Margin = "Margin",
Settlement = "Settlement",
}
export enum AuctionTrigger {
Batch = "Batch",
Liquidity = "Liquidity",
Opening = "Opening",
Price = "Price",
Unspecified = "Unspecified",
}
/**
* The current state of a market
*/
export enum MarketState {
Active = "Active",
Cancelled = "Cancelled",
Closed = "Closed",
Pending = "Pending",
Proposed = "Proposed",
Rejected = "Rejected",
Settled = "Settled",
Suspended = "Suspended",
TradingTerminated = "TradingTerminated",
}
/**
* What market trading mode are we in
*/
export enum MarketTradingMode {
BatchAuction = "BatchAuction",
Continuous = "Continuous",
MonitoringAuction = "MonitoringAuction",
OpeningAuction = "OpeningAuction",
}
export enum NodeStatus {
NonValidator = "NonValidator",
Validator = "Validator",
}
/**
* Reason for the proposal being rejected by the core node
*/
export enum ProposalRejectionReason {
CloseTimeTooLate = "CloseTimeTooLate",
CloseTimeTooSoon = "CloseTimeTooSoon",
CouldNotInstantiateMarket = "CouldNotInstantiateMarket",
EnactTimeTooLate = "EnactTimeTooLate",
EnactTimeTooSoon = "EnactTimeTooSoon",
IncompatibleTimestamps = "IncompatibleTimestamps",
InsufficientTokens = "InsufficientTokens",
InvalidAsset = "InvalidAsset",
InvalidAssetDetails = "InvalidAssetDetails",
InvalidFeeAmount = "InvalidFeeAmount",
InvalidFutureMaturityTimestamp = "InvalidFutureMaturityTimestamp",
InvalidFutureProduct = "InvalidFutureProduct",
InvalidInstrumentSecurity = "InvalidInstrumentSecurity",
InvalidRiskParameter = "InvalidRiskParameter",
InvalidShape = "InvalidShape",
MajorityThresholdNotReached = "MajorityThresholdNotReached",
MarketMissingLiquidityCommitment = "MarketMissingLiquidityCommitment",
MissingBuiltinAssetField = "MissingBuiltinAssetField",
MissingCommitmentAmount = "MissingCommitmentAmount",
MissingERC20ContractAddress = "MissingERC20ContractAddress",
NetworkParameterInvalidKey = "NetworkParameterInvalidKey",
NetworkParameterInvalidValue = "NetworkParameterInvalidValue",
NetworkParameterValidationFailed = "NetworkParameterValidationFailed",
NoProduct = "NoProduct",
NoRiskParameters = "NoRiskParameters",
NoTradingMode = "NoTradingMode",
NodeValidationFailed = "NodeValidationFailed",
OpeningAuctionDurationTooLarge = "OpeningAuctionDurationTooLarge",
OpeningAuctionDurationTooSmall = "OpeningAuctionDurationTooSmall",
ParticipationThresholdNotReached = "ParticipationThresholdNotReached",
ProductMaturityIsPassed = "ProductMaturityIsPassed",
UnsupportedProduct = "UnsupportedProduct",
UnsupportedTradingMode = "UnsupportedTradingMode",
}
/**
* Various states a proposal can transition through:
* Open ->
* - Passed -> Enacted.
* - Rejected.
* Proposal can enter Failed state from any other state.
*/
export enum ProposalState {
Declined = "Declined",
Enacted = "Enacted",
Failed = "Failed",
Open = "Open",
Passed = "Passed",
Rejected = "Rejected",
WaitingForNodeVote = "WaitingForNodeVote",
}
export enum VoteValue {
No = "No",
Yes = "Yes",
}
//==============================================================
// END Enums and Input Objects
//==============================================================

View File

@ -4,7 +4,7 @@ import { useState } from 'react';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
import debounce from 'lodash.debounce'; import debounce from 'lodash.debounce';
import { Guess, GuessVariables } from './__generated__/Guess'; import { Guess, GuessVariables } from '@vegaprotocol/graphql';
const TX_LENGTH = 64; const TX_LENGTH = 64;

View File

@ -1,7 +1,7 @@
import { gql, useQuery } from '@apollo/client'; import { gql, useQuery } from '@apollo/client';
import React from 'react'; import React from 'react';
import { SyntaxHighlighter } from '../../components/syntax-highlighter'; import { SyntaxHighlighter } from '../../components/syntax-highlighter';
import { AssetsQuery } from './__generated__/AssetsQuery'; import { AssetsQuery } from '@vegaprotocol/graphql';
export const ASSETS_QUERY = gql` export const ASSETS_QUERY = gql`
query AssetsQuery { query AssetsQuery {
@ -11,7 +11,6 @@ export const ASSETS_QUERY = gql`
symbol symbol
totalSupply totalSupply
decimals decimals
minLpStake
source { source {
... on ERC20 { ... on ERC20 {
contractAddress contractAddress

View File

@ -34,10 +34,7 @@ const Block = () => {
<TableRow modifier="bordered"> <TableRow modifier="bordered">
<TableHeader scope="row">Mined by</TableHeader> <TableHeader scope="row">Mined by</TableHeader>
<TableCell modifier="bordered"> <TableCell modifier="bordered">
<Link <Link className="text-vega-yellow" to={'/validators'}>
className="text-vega-yellow"
to={"/validators"}
>
{header.proposer_address} {header.proposer_address}
</Link> </Link>
</TableCell> </TableCell>

View File

@ -4,7 +4,7 @@ import { SyntaxHighlighter } from '../../components/syntax-highlighter';
import { import {
ProposalsQuery, ProposalsQuery,
ProposalsQuery_proposals_terms_change, ProposalsQuery_proposals_terms_change,
} from './__generated__/ProposalsQuery'; } from '@vegaprotocol/graphql';
export function getProposalName(change: ProposalsQuery_proposals_terms_change) { export function getProposalName(change: ProposalsQuery_proposals_terms_change) {
if (change.__typename === 'NewAsset') { if (change.__typename === 'NewAsset') {

View File

@ -1,5 +1,5 @@
import { gql, useQuery } from '@apollo/client'; import { gql, useQuery } from '@apollo/client';
import { MarketsQuery } from './__generated__/MarketsQuery'; import { MarketsQuery } from '@vegaprotocol/graphql';
import React from 'react'; import React from 'react';
import { SyntaxHighlighter } from '../../components/syntax-highlighter'; import { SyntaxHighlighter } from '../../components/syntax-highlighter';
@ -26,7 +26,6 @@ const MARKETS_QUERY = gql`
code code
product { product {
... on Future { ... on Future {
maturity
settlementAsset { settlementAsset {
id id
name name

View File

@ -1,5 +1,5 @@
import { gql, useQuery } from '@apollo/client'; import { gql, useQuery } from '@apollo/client';
import { NetworkParametersQuery } from './__generated__/NetworkParametersQuery'; import { NetworkParametersQuery } from '@vegaprotocol/graphql';
export const NETWORK_PARAMETERS_QUERY = gql` export const NETWORK_PARAMETERS_QUERY = gql`
query NetworkParametersQuery { query NetworkParametersQuery {

View File

@ -8,7 +8,7 @@ import { TendermintSearchTransactionResponse } from '../tendermint-transaction-r
import { import {
PartyAssetsQuery, PartyAssetsQuery,
PartyAssetsQueryVariables, PartyAssetsQueryVariables,
} from './__generated__/PartyAssetsQuery'; } from '@vegaprotocol/graphql';
const PARTY_ASSETS_QUERY = gql` const PARTY_ASSETS_QUERY = gql`
query PartyAssetsQuery($partyId: ID!) { query PartyAssetsQuery($partyId: ID!) {
@ -58,7 +58,7 @@ const Party = () => {
{ {
// Don't cache data for this query, party information can move quite quickly // Don't cache data for this query, party information can move quite quickly
fetchPolicy: 'network-only', fetchPolicy: 'network-only',
variables: { partyId: party?.replace('0x', '') }, variables: { partyId: party?.replace('0x', '') || '' },
skip: !party, skip: !party,
} }
); );

View File

@ -3,7 +3,7 @@ import React from 'react';
import { DATA_SOURCES } from '../../config'; import { DATA_SOURCES } from '../../config';
import useFetch from '../../hooks/use-fetch'; import useFetch from '../../hooks/use-fetch';
import { TendermintValidatorsResponse } from './tendermint-validator-response'; import { TendermintValidatorsResponse } from './tendermint-validator-response';
import { NodesQuery } from './__generated__/NodesQuery'; import { NodesQuery } from '@vegaprotocol/graphql';
const NODES_QUERY = gql` const NODES_QUERY = gql`
query NodesQuery { query NodesQuery {
@ -26,8 +26,6 @@ const NODES_QUERY = gql`
online online
} }
status status
score
normalisedScore
name name
} }
} }

View File

@ -5,7 +5,7 @@
"next", "next",
"next/core-web-vitals" "next/core-web-vitals"
], ],
"ignorePatterns": ["!**/*", "__generated__"], "ignorePatterns": ["!**/*"],
"overrides": [ "overrides": [
{ {
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],

View File

@ -1,12 +0,0 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
//==============================================================
// START Enums and Input Objects
//==============================================================
//==============================================================
// END Enums and Input Objects
//==============================================================

View File

@ -1,9 +0,0 @@
module.exports = {
client: {
service: {
name: 'vega',
url: process.env.NX_VEGA_URL,
},
includes: ['{components,lib,pages}/**/*.{ts,tsx,js,jsx,graphql}'],
},
};

View File

@ -0,0 +1,74 @@
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
import { DealTicket } from '@vegaprotocol/deal-ticket';
import { OrderStatus } from '@vegaprotocol/graphql';
import { useOrderSubmit } from '../../hooks/use-order-submit';
import { useEffect, useState } from 'react';
import { VegaTxStatus } from '../../hooks/use-vega-transaction';
import { OrderDialog } from './order-dialog';
export const DealTicketContainer = ({ market }) => {
const [orderDialogOpen, setOrderDialogOpen] = useState(false);
const { submit, transaction, finalizedOrder, reset } = useOrderSubmit(market);
const getDialogIntent = (status: VegaTxStatus) => {
if (finalizedOrder) {
if (
finalizedOrder.status === OrderStatus.Active ||
finalizedOrder.status === OrderStatus.Filled ||
finalizedOrder.status === OrderStatus.PartiallyFilled
) {
return Intent.Success;
}
if (finalizedOrder.status === OrderStatus.Parked) {
return Intent.Warning;
}
return Intent.Danger;
}
if (status === VegaTxStatus.Rejected) {
return Intent.Danger;
}
return Intent.Progress;
};
useEffect(() => {
if (transaction.status !== VegaTxStatus.Default) {
setOrderDialogOpen(true);
}
}, [transaction.status]);
return (
<>
<DealTicket
market={market}
submit={submit}
transactionStatus={
transaction.status === VegaTxStatus.AwaitingConfirmation ||
transaction.status === VegaTxStatus.Pending
? 'pending'
: 'default'
}
/>
<Dialog
open={orderDialogOpen}
onChange={(isOpen) => {
setOrderDialogOpen(isOpen);
// If closing reset
if (!isOpen) {
reset();
}
}}
intent={getDialogIntent(transaction.status)}
>
<OrderDialog
transaction={transaction}
finalizedOrder={finalizedOrder}
/>
</Dialog>
</>
);
};

View File

@ -0,0 +1 @@
export * from './deal-ticket-container';

View File

@ -0,0 +1,95 @@
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
import { ReactNode } from 'react';
import {
TransactionState,
VegaTxStatus,
} from '../../hooks/use-vega-transaction';
import { OrderEvent_busEvents_event_Order } from '@vegaprotocol/graphql';
interface OrderDialogProps {
transaction: TransactionState;
finalizedOrder: OrderEvent_busEvents_event_Order | null;
}
export const OrderDialog = ({
transaction,
finalizedOrder,
}: OrderDialogProps) => {
// TODO: When wallets support confirming transactions return UI for 'awaiting confirmation' step
// Rejected by wallet
if (transaction.status === VegaTxStatus.Rejected) {
return (
<OrderDialogWrapper
title="Order rejected by wallet"
icon={<Icon name="warning-sign" size={20} />}
>
{transaction.error && (
<pre className="text-ui break-all whitespace-pre-wrap">
{JSON.stringify(transaction.error, null, 2)}
</pre>
)}
</OrderDialogWrapper>
);
}
// Pending consensus
if (!finalizedOrder) {
return (
<OrderDialogWrapper
title="Awaiting network confirmation"
icon={<Loader />}
>
{transaction.hash && (
<p className="break-all">Tx hash: {transaction.hash}</p>
)}
</OrderDialogWrapper>
);
}
// Order on network but was rejected
if (finalizedOrder.status === 'Rejected') {
return (
<OrderDialogWrapper
title="Order failed"
icon={<Icon name="warning-sign" size={20} />}
>
<p>Reason: {finalizedOrder.rejectionReason}</p>
</OrderDialogWrapper>
);
}
return (
<OrderDialogWrapper
title="Order placed"
icon={<Icon name="tick" size={20} />}
>
<p>Status: {finalizedOrder.status}</p>
<p>Market: {finalizedOrder.market.name}</p>
<p>Amount: {finalizedOrder.size}</p>
{finalizedOrder.type === 'Limit' && <p>Price: {finalizedOrder.price}</p>}
</OrderDialogWrapper>
);
};
interface OrderDialogWrapperProps {
children: ReactNode;
icon: ReactNode;
title: string;
}
const OrderDialogWrapper = ({
children,
icon,
title,
}: OrderDialogWrapperProps) => {
return (
<div className="flex gap-12 max-w-full">
<div className="pt-8 fill-current">{icon}</div>
<div className="flex-1">
<h1 className="text-h4">{title}</h1>
{children}
</div>
</div>
);
};

View File

@ -1,7 +1,7 @@
import { OperationVariables, QueryHookOptions, useQuery } from '@apollo/client'; import { OperationVariables, QueryHookOptions, useQuery } from '@apollo/client';
import classNames from 'classnames';
import { DocumentNode } from 'graphql'; import { DocumentNode } from 'graphql';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Splash } from '@vegaprotocol/ui-toolkit';
interface PageQueryContainerProps<TData, TVariables> { interface PageQueryContainerProps<TData, TVariables> {
query: DocumentNode; query: DocumentNode;
@ -15,19 +15,13 @@ export const PageQueryContainer = <TData, TVariables = OperationVariables>({
children, children,
}: PageQueryContainerProps<TData, TVariables>) => { }: PageQueryContainerProps<TData, TVariables>) => {
const { data, loading, error } = useQuery<TData, TVariables>(query, options); const { data, loading, error } = useQuery<TData, TVariables>(query, options);
const splashClasses = classNames(
'w-full h-full',
'flex items-center justify-center'
);
if (loading || !data) { if (loading || !data) {
return <div className={splashClasses}>Loading...</div>; return <Splash>Loading...</Splash>;
} }
if (error) { if (error) {
return ( return <Splash>Something went wrong: {error.message}</Splash>;
<div className={splashClasses}>Something went wrong: {error.message}</div>
);
} }
return <>{children(data)}</>; return <>{children(data)}</>;

View File

@ -0,0 +1,131 @@
import { gql, useApolloClient } from '@apollo/client';
import { singletonHook } from 'react-singleton-hook';
import {
Markets,
Markets_markets,
MarketDataSub,
MarketDataSub_marketData,
} from '@vegaprotocol/graphql';
import { useCallback, useEffect, useState } from 'react';
const MARKET_DATA_FRAGMENT = gql`
fragment MarketDataFields on MarketData {
market {
id
state
tradingMode
}
bestBidPrice
bestOfferPrice
markPrice
}
`;
const MARKETS_QUERY = gql`
${MARKET_DATA_FRAGMENT}
query Markets {
markets {
id
name
decimalPlaces
data {
...MarketDataFields
}
tradableInstrument {
instrument {
code
product {
... on Future {
settlementAsset {
symbol
}
}
}
}
}
}
}
`;
const MARKET_DATA_SUB = gql`
${MARKET_DATA_FRAGMENT}
subscription MarketDataSub {
marketData {
...MarketDataFields
}
}
`;
export const useMarketsImpl = () => {
const client = useApolloClient();
const [markets, setMarkets] = useState<Markets_markets[]>([]);
const [error, setError] = useState<Error | null>(null);
const [loading, setLoading] = useState(false);
const mergeMarketData = useCallback((update: MarketDataSub_marketData) => {
setMarkets((curr) => {
return curr.map((m) => {
if (update.market.id === m.id) {
return {
...m,
data: update,
};
}
return m;
});
});
}, []);
// Make initial fetch
useEffect(() => {
const fetchOrders = async () => {
setLoading(true);
try {
const res = await client.query<Markets>({
query: MARKETS_QUERY,
});
if (!res.data.markets?.length) return;
setMarkets(res.data.markets);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchOrders();
}, [mergeMarketData, client]);
// Start subscription
useEffect(() => {
const sub = client
// This data callback will unfortunately be called separately with an update for every market,
// perhaps we should batch this somehow...
.subscribe<MarketDataSub>({
query: MARKET_DATA_SUB,
})
.subscribe(({ data }) => {
mergeMarketData(data.marketData);
});
return () => {
if (sub) {
sub.unsubscribe();
}
};
}, [client, mergeMarketData]);
return { markets, error, loading };
};
const initial = {
markets: [],
error: null,
loading: false,
};
export const useMarkets = singletonHook(initial, useMarketsImpl);

View File

@ -0,0 +1,153 @@
import { MockedProvider } from '@apollo/client/testing';
import { act, renderHook } from '@testing-library/react-hooks';
import { Order } from '@vegaprotocol/deal-ticket';
import {
VegaKeyExtended,
VegaWalletContext,
VegaWalletContextShape,
} from '@vegaprotocol/wallet';
import { OrderSide, OrderTimeInForce, OrderType } from '@vegaprotocol/wallet';
import { ReactNode } from 'react';
import { useOrderSubmit } from './use-order-submit';
import { VegaTxStatus } from './use-vega-transaction';
const defaultWalletContext = {
keypair: null,
keypairs: [],
sendTx: jest.fn().mockReturnValue(Promise.resolve(null)),
connect: jest.fn(),
disconnect: jest.fn(),
selectPublicKey: jest.fn(),
connector: null,
};
function setup(
context?: Partial<VegaWalletContextShape>,
market = { id: 'market-id', decimalPlaces: 2 }
) {
const wrapper = ({ children }: { children: ReactNode }) => (
<MockedProvider>
<VegaWalletContext.Provider
value={{ ...defaultWalletContext, ...context }}
>
{children}
</VegaWalletContext.Provider>
</MockedProvider>
);
return renderHook(() => useOrderSubmit(market), { wrapper });
}
test('Has the correct default state', () => {
const { result } = setup();
expect(typeof result.current.submit).toEqual('function');
expect(typeof result.current.reset).toEqual('function');
expect(result.current.transaction.status).toEqual(VegaTxStatus.Default);
expect(result.current.transaction.hash).toEqual(null);
expect(result.current.transaction.error).toEqual(null);
});
test('Should not sendTx if no keypair', async () => {
const mockSendTx = jest.fn();
const { result } = setup({ sendTx: mockSendTx, keypairs: [], keypair: null });
await act(async () => {
result.current.submit({} as Order);
});
expect(mockSendTx).not.toHaveBeenCalled();
});
test('Should not sendTx side is not specified', async () => {
const mockSendTx = jest.fn();
const keypair = {
pub: '0x123',
} as VegaKeyExtended;
const { result } = setup({
sendTx: mockSendTx,
keypairs: [keypair],
keypair,
});
await act(async () => {
result.current.submit({} as Order);
});
expect(mockSendTx).not.toHaveBeenCalled();
});
test('Create an Id if a signature is returned', async () => {
const signature =
'597a7706491e6523c091bab1e4d655b62c45a224e80f6cd92ac366aa5dd9a070cc7dd3c6919cb07b81334b876c662dd43bdbe5e827c8baa17a089feb654fab0b';
const expectedId =
'2FE09B0E2E6ED35F8883802629C7D609D3CC2FC9CE3CEC0B7824A0D581BD3747';
const successObj = {
tx: {
inputData: 'input-data',
signature: {
algo: 'algo',
version: 1,
value: signature,
},
},
txHash: '0x123',
};
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve(successObj));
const keypair = {
pub: '0x123',
} as VegaKeyExtended;
const { result } = setup({
sendTx: mockSendTx,
keypairs: [keypair],
keypair,
});
await act(async () => {
result.current.submit({
type: OrderType.Market,
side: OrderSide.Buy,
size: '1',
timeInForce: OrderTimeInForce.FOK,
});
});
expect(result.current.id).toEqual(expectedId);
});
test('Should submit a correctly formatted order', async () => {
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve({}));
const keypair = {
pub: '0x123',
} as VegaKeyExtended;
const market = {
id: 'market-id',
decimalPlaces: 2,
};
const { result } = setup(
{
sendTx: mockSendTx,
keypairs: [keypair],
keypair,
},
market
);
const order = {
type: OrderType.Limit,
size: '10',
timeInForce: OrderTimeInForce.GTT,
side: OrderSide.Buy,
price: '1234567.89',
expiration: new Date('2022-01-01'),
};
await act(async () => {
result.current.submit(order);
});
expect(mockSendTx).toHaveBeenCalledWith({
pubKey: keypair.pub,
propagate: true,
orderSubmission: {
type: OrderType.Limit,
marketId: market.id, // Market provided from hook arugment
size: '10',
side: OrderSide.Buy,
timeInForce: OrderTimeInForce.GTT,
price: '123456789', // Decimal removed
expiresAt: order.expiration.getTime() + '000000', // Nanoseconds appened
},
});
});

View File

@ -0,0 +1,157 @@
import { useCallback, useEffect, useState } from 'react';
import { gql, useSubscription } from '@apollo/client';
import { ethers } from 'ethers';
import { SHA3 } from 'sha3';
import { Order } from '@vegaprotocol/deal-ticket';
import { OrderType, useVegaWallet } from '@vegaprotocol/wallet';
import { useVegaTransaction } from './use-vega-transaction';
import {
OrderEvent,
OrderEventVariables,
OrderEvent_busEvents_event_Order,
} from '@vegaprotocol/graphql';
import { removeDecimal } from '@vegaprotocol/react-helpers';
const ORDER_EVENT_SUB = gql`
subscription OrderEvent($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Order]) {
eventId
block
type
event {
... on Order {
type
id
status
rejectionReason
createdAt
size
price
market {
name
}
}
}
}
}
`;
interface UseOrderSubmitMarket {
id: string;
decimalPlaces: number;
}
export const useOrderSubmit = (market: UseOrderSubmitMarket) => {
const { keypair } = useVegaWallet();
const { send, transaction, reset: resetTransaction } = useVegaTransaction();
const [id, setId] = useState('');
const [finalizedOrder, setFinalizedOrder] =
useState<OrderEvent_busEvents_event_Order | null>(null);
// Start a subscription looking for the newly created order
useSubscription<OrderEvent, OrderEventVariables>(ORDER_EVENT_SUB, {
variables: { partyId: keypair?.pub || '' },
skip: !id,
onSubscriptionData: ({ subscriptionData }) => {
if (!subscriptionData.data.busEvents.length) {
return;
}
// No types available for the subscription result
const matchingOrderEvent = subscriptionData.data.busEvents.find((e) => {
if (e.event.__typename !== 'Order') {
return false;
}
if (e.event.id === id) {
return true;
}
return false;
});
if (
matchingOrderEvent &&
matchingOrderEvent.event.__typename === 'Order'
) {
setFinalizedOrder(matchingOrderEvent.event);
}
},
});
useEffect(() => {
if (finalizedOrder) {
resetTransaction();
}
}, [finalizedOrder, resetTransaction]);
const submit = useCallback(
async (order: Order) => {
if (!keypair || !order.side) {
return;
}
setFinalizedOrder(null);
const res = await send({
pubKey: keypair.pub,
propagate: true,
orderSubmission: {
marketId: market.id,
price:
order.type === OrderType.Market
? undefined
: removeDecimal(order.price, market.decimalPlaces),
size: order.size,
type: order.type,
side: order.side,
timeInForce: order.timeInForce,
expiresAt: order.expiration
? // Wallet expects timestamp in nanoseconds, we don't have that level of accuracy so
// just append 6 zeroes
order.expiration.getTime().toString() + '000000'
: undefined,
},
});
if (res?.signature) {
setId(determineId(res.signature).toUpperCase());
}
},
[market, keypair, send]
);
const reset = useCallback(() => {
resetTransaction();
setFinalizedOrder(null);
setId('');
}, [resetTransaction]);
return {
transaction,
finalizedOrder,
id,
submit,
reset,
};
};
/**
* This function creates an ID in the same way that core does on the backend. This way we
* Can match up the newly created order with incoming orders via a subscription
*/
export const determineId = (sig: string) => {
// Prepend 0x
if (sig.slice(0, 2) !== '0x') {
sig = '0x' + sig;
}
// Create the ID
const hash = new SHA3(256);
const bytes = ethers.utils.arrayify(sig);
hash.update(Buffer.from(bytes));
const id = ethers.utils.hexlify(hash.digest());
// Remove 0x as core doesn't keep them in the API
return id.substring(2);
};

View File

@ -0,0 +1,98 @@
import { act, renderHook } from '@testing-library/react-hooks';
import {
OrderSubmission,
VegaWalletContext,
VegaWalletContextShape,
} from '@vegaprotocol/wallet';
import { ReactNode } from 'react';
import { useVegaTransaction, VegaTxStatus } from './use-vega-transaction';
const defaultWalletContext = {
keypair: null,
keypairs: [],
sendTx: jest.fn(),
connect: jest.fn(),
disconnect: jest.fn(),
selectPublicKey: jest.fn(),
connector: null,
};
function setup(context?: Partial<VegaWalletContextShape>) {
const wrapper = ({ children }: { children: ReactNode }) => (
<VegaWalletContext.Provider value={{ ...defaultWalletContext, ...context }}>
{children}
</VegaWalletContext.Provider>
);
return renderHook(() => useVegaTransaction(), { wrapper });
}
test('Has the correct default state', () => {
const { result } = setup();
expect(result.current.transaction.status).toEqual(VegaTxStatus.Default);
expect(result.current.transaction.hash).toEqual(null);
expect(result.current.transaction.signature).toEqual(null);
expect(result.current.transaction.error).toEqual(null);
expect(typeof result.current.reset).toEqual('function');
expect(typeof result.current.send).toEqual('function');
});
test('If provider returns null status should be default', async () => {
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve(null));
const { result } = setup({ sendTx: mockSendTx });
await act(async () => {
result.current.send({} as OrderSubmission);
});
expect(result.current.transaction.status).toEqual(VegaTxStatus.Default);
});
test('Handles a single error', async () => {
const errorMessage = 'Oops error!';
const mockSendTx = jest
.fn()
.mockReturnValue(Promise.resolve({ error: errorMessage }));
const { result } = setup({ sendTx: mockSendTx });
await act(async () => {
result.current.send({} as OrderSubmission);
});
expect(result.current.transaction.status).toEqual(VegaTxStatus.Rejected);
expect(result.current.transaction.error).toEqual({ error: errorMessage });
});
test('Handles multiple errors', async () => {
const errorObj = {
errors: {
something: 'Went wrong!',
},
};
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve(errorObj));
const { result } = setup({ sendTx: mockSendTx });
await act(async () => {
result.current.send({} as OrderSubmission);
});
expect(result.current.transaction.status).toEqual(VegaTxStatus.Rejected);
expect(result.current.transaction.error).toEqual(errorObj);
});
test('Returns the signature if successful', async () => {
const successObj = {
tx: {
inputData: 'input-data',
signature: {
algo: 'algo',
version: 1,
value: 'signature',
},
},
txHash: '0x123',
};
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve(successObj));
const { result } = setup({ sendTx: mockSendTx });
await act(async () => {
result.current.send({} as OrderSubmission);
});
expect(result.current.transaction.status).toEqual(VegaTxStatus.Pending);
expect(result.current.transaction.hash).toEqual(successObj.txHash);
expect(result.current.transaction.signature).toEqual(
successObj.tx.signature.value
);
});

View File

@ -0,0 +1,89 @@
import { useCallback, useState } from 'react';
import { useVegaWallet, SendTxError, Transaction } from '@vegaprotocol/wallet';
export enum VegaTxStatus {
Default = 'Default',
AwaitingConfirmation = 'AwaitingConfirmation',
Rejected = 'Rejected',
Pending = 'Pending',
}
export interface TransactionState {
status: VegaTxStatus;
error: object | null;
hash: string | null;
signature: string | null;
}
export const useVegaTransaction = () => {
const { sendTx } = useVegaWallet();
const [transaction, _setTransaction] = useState<TransactionState>({
status: VegaTxStatus.Default,
error: null,
hash: null,
signature: null,
});
const setTransaction = useCallback((update: Partial<TransactionState>) => {
_setTransaction((curr) => ({
...curr,
...update,
}));
}, []);
const handleError = useCallback(
(error: SendTxError) => {
setTransaction({ error, status: VegaTxStatus.Rejected });
},
[setTransaction]
);
const send = useCallback(
async (tx: Transaction) => {
setTransaction({
error: null,
hash: null,
signature: null,
status: VegaTxStatus.AwaitingConfirmation,
});
const res = await sendTx(tx);
if (res === null) {
setTransaction({ status: VegaTxStatus.Default });
return null;
}
if ('error' in res) {
handleError(res);
return null;
} else if ('errors' in res) {
handleError(res);
return null;
} else if (res.tx && res.txHash) {
setTransaction({
status: VegaTxStatus.Pending,
hash: res.txHash,
signature: res.tx.signature.value,
});
return {
signature: res.tx.signature?.value,
};
}
return null;
},
[sendTx, handleError, setTransaction]
);
const reset = useCallback(() => {
setTransaction({
error: null,
hash: null,
signature: null,
status: VegaTxStatus.Default,
});
}, [setTransaction]);
return { send, transaction, reset };
};

View File

@ -1,6 +1,15 @@
import { ApolloClient, from, HttpLink, InMemoryCache } from '@apollo/client'; import {
ApolloClient,
split,
from,
HttpLink,
InMemoryCache,
} from '@apollo/client';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { getMainDefinition } from '@apollo/client/utilities';
import { onError } from '@apollo/client/link/error'; import { onError } from '@apollo/client/link/error';
import { RetryLink } from '@apollo/client/link/retry'; import { RetryLink } from '@apollo/client/link/retry';
import { createClient as createWSClient } from 'graphql-ws';
export function createClient(base?: string) { export function createClient(base?: string) {
if (!base) { if (!base) {
@ -14,13 +23,18 @@ export function createClient(base?: string) {
const cache = new InMemoryCache({ const cache = new InMemoryCache({
typePolicies: { typePolicies: {
Query: {},
Account: { Account: {
keyFields: false, keyFields: false,
fields: { fields: {
balanceFormatted: {}, balanceFormatted: {},
}, },
}, },
Instrument: {
keyFields: false,
},
MarketData: {
keyFields: ['market', ['id']],
},
Node: { Node: {
keyFields: false, keyFields: false,
}, },
@ -40,6 +54,28 @@ export function createClient(base?: string) {
credentials: 'same-origin', credentials: 'same-origin',
}); });
const wsLink = process.browser
? new GraphQLWsLink(
createWSClient({
url: urlWS.href,
})
)
: null;
const splitLink = process.browser
? split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink
)
: httpLink;
const errorLink = onError(({ graphQLErrors, networkError }) => { const errorLink = onError(({ graphQLErrors, networkError }) => {
console.log(graphQLErrors); console.log(graphQLErrors);
console.log(networkError); console.log(networkError);
@ -47,7 +83,7 @@ export function createClient(base?: string) {
return new ApolloClient({ return new ApolloClient({
connectToDevTools: process.env['NODE_ENV'] === 'development', connectToDevTools: process.env['NODE_ENV'] === 'development',
link: from([errorLink, retryLink, httpLink]), link: from([errorLink, retryLink, splitLink]),
cache, cache,
}); });
} }

View File

@ -5,6 +5,7 @@ import { ThemeContext } from '@vegaprotocol/react-helpers';
import { VegaConnectDialog, VegaWalletProvider } from '@vegaprotocol/wallet'; import { VegaConnectDialog, VegaWalletProvider } from '@vegaprotocol/wallet';
import { Connectors } from '../lib/connectors'; import { Connectors } from '../lib/connectors';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { SingletonHooksContainer } from 'react-singleton-hook';
import { createClient } from '../lib/apollo-client'; import { createClient } from '../lib/apollo-client';
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit'; import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
import { ApolloProvider } from '@apollo/client'; import { ApolloProvider } from '@apollo/client';
@ -17,9 +18,7 @@ import './styles.css';
function VegaTradingApp({ Component, pageProps }: AppProps) { function VegaTradingApp({ Component, pageProps }: AppProps) {
const client = useMemo( const client = useMemo(
() => () =>
createClient( createClient(process.env['NX_VEGA_URL'] || 'https://lb.testnet.vega.xyz'),
process.env['NX_VEGA_URL'] || 'https://n03.stagnet2.vega.xyz'
),
[] []
); );
const [dialogOpen, setDialogOpen] = useState(false); const [dialogOpen, setDialogOpen] = useState(false);
@ -36,6 +35,7 @@ function VegaTradingApp({ Component, pageProps }: AppProps) {
<ThemeContext.Provider value={theme}> <ThemeContext.Provider value={theme}>
<ApolloProvider client={client}> <ApolloProvider client={client}>
<VegaWalletProvider> <VegaWalletProvider>
<SingletonHooksContainer />
<AppLoader> <AppLoader>
<Head> <Head>
<title>Welcome to trading!</title> <title>Welcome to trading!</title>

View File

@ -2,6 +2,7 @@ import {
AgGridDynamic as AgGrid, AgGridDynamic as AgGrid,
Button, Button,
Callout, Callout,
Intent,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { AgGridColumn } from 'ag-grid-react'; import { AgGridColumn } from 'ag-grid-react';
@ -15,7 +16,7 @@ export function Index() {
<div className="m-24"> <div className="m-24">
<div className="mb-24"> <div className="mb-24">
<Callout <Callout
intent="help" intent={Intent.Help}
title="Welcome to Vega Trading App" title="Welcome to Vega Trading App"
iconName="endorsed" iconName="endorsed"
headingLevel={1} headingLevel={1}

View File

@ -1,8 +1,9 @@
import { gql } from '@apollo/client'; import { gql } from '@apollo/client';
import { Market, MarketVariables } from '@vegaprotocol/graphql';
import { Splash } from '@vegaprotocol/ui-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import debounce from 'lodash.debounce'; import debounce from 'lodash.debounce';
import { Market, MarketVariables } from './__generated__/Market';
import { PageQueryContainer } from '../../components/page-query-container'; import { PageQueryContainer } from '../../components/page-query-container';
import { TradeGrid, TradePanels } from './trade-grid'; import { TradeGrid, TradePanels } from './trade-grid';
@ -12,12 +13,34 @@ const MARKET_QUERY = gql`
market(id: $marketId) { market(id: $marketId) {
id id
name name
decimalPlaces
state
tradingMode
tradableInstrument {
instrument {
product {
... on Future {
quoteName
settlementAsset {
id
symbol
name
}
}
}
}
}
trades { trades {
id id
price price
size size
createdAt createdAt
} }
depth {
lastTrade {
price
}
}
} }
} }
`; `;
@ -38,15 +61,20 @@ const MarketPage = () => {
marketId: Array.isArray(marketId) ? marketId[0] : marketId, marketId: Array.isArray(marketId) ? marketId[0] : marketId,
}, },
skip: !marketId, skip: !marketId,
fetchPolicy: 'network-only',
}} }}
> >
{({ market }) => {({ market }) => {
w > 1050 ? ( if (!market) {
return <Splash>Market not found</Splash>;
}
return w > 960 ? (
<TradeGrid market={market} /> <TradeGrid market={market} />
) : ( ) : (
<TradePanels market={market} /> <TradePanels market={market} />
) );
} }}
</PageQueryContainer> </PageQueryContainer>
); );
}; };

View File

@ -1,55 +0,0 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
// ====================================================
// GraphQL query operation: Market
// ====================================================
export interface Market_market_trades {
__typename: 'Trade';
/**
* The hash of the trade data
*/
id: string;
/**
* The price of the trade (probably initially the passive order price, other determination algorithms are possible though) (uint64)
*/
price: string;
/**
* The number of contracts trades, will always be <= the remaining size of both orders immediately before the trade (uint64)
*/
size: string;
/**
* RFC3339Nano time for when the trade occurred
*/
createdAt: string;
}
export interface Market_market {
__typename: 'Market';
/**
* Market ID
*/
id: string;
/**
* Market full name
*/
name: string;
/**
* Trades on a market
*/
trades: Market_market_trades[] | null;
}
export interface Market {
/**
* An instrument that is trading on the VEGA network
*/
market: Market_market | null;
}
export interface MarketVariables {
marketId: string;
}

View File

@ -1,23 +0,0 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
// ====================================================
// GraphQL query operation: Markets
// ====================================================
export interface Markets_markets {
__typename: "Market";
/**
* Market ID
*/
id: string;
}
export interface Markets {
/**
* One or more instruments that are trading on the VEGA network
*/
markets: Markets_markets[] | null;
}

View File

@ -1,40 +1,28 @@
import { gql } from '@apollo/client'; import { Markets } from '@vegaprotocol/graphql';
import { PageQueryContainer } from '../../components/page-query-container';
import Link from 'next/link';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { Markets } from './__generated__/Markets'; import { MarketListTable } from '@vegaprotocol/market-list';
import { useMarkets } from '../../hooks/use-markets';
const MARKETS_QUERY = gql` import { Splash } from '@vegaprotocol/ui-toolkit';
query Markets {
markets {
id
}
}
`;
const Markets = () => { const Markets = () => {
const { pathname } = useRouter(); const { pathname, push } = useRouter();
const { markets, error, loading } = useMarkets();
if (error) {
return <Splash>Something went wrong: {error.message}</Splash>;
}
if (loading) {
return <Splash>Loading...</Splash>;
}
return ( return (
<PageQueryContainer<Markets> query={MARKETS_QUERY}> <MarketListTable
{(data) => ( markets={markets}
<> onRowClicked={(id) =>
<h1>Markets</h1> push(`${pathname}/${id}?portfolio=orders&trade=orderbook`)
<ul> }
{data.markets.map((m) => ( />
<li key={m.id}>
<Link
href={`${pathname}/${m.id}?portfolio=orders&trade=orderbook`}
passHref={true}
>
<a>View market: {m.id}</a>
</Link>
</li>
))}
</ul>
</>
)}
</PageQueryContainer>
); );
}; };

View File

@ -1,9 +1,26 @@
import { Market_market } from '@vegaprotocol/graphql';
import classNames from 'classnames'; import classNames from 'classnames';
import AutoSizer from 'react-virtualized-auto-sizer'; import AutoSizer from 'react-virtualized-auto-sizer';
import { useState, ReactNode } from 'react'; import { useState, ReactNode } from 'react';
import { TradingView, TradingViews } from '@vegaprotocol/react-helpers';
import { Market_market } from './__generated__/Market';
import { GridTab, GridTabs } from './grid-tabs'; import { GridTab, GridTabs } from './grid-tabs';
import { DealTicketContainer } from '../../components/deal-ticket-container';
const Chart = () => <div>TODO: Chart</div>;
const Orderbook = () => <div>TODO: Orderbook</div>;
const Orders = () => <div>TODO: Orders</div>;
const Positions = () => <div>TODO: Positions</div>;
const Collateral = () => <div>TODO: Collateral</div>;
type TradingView = keyof typeof TradingViews;
const TradingViews = {
chart: Chart,
ticket: DealTicketContainer,
orderbook: Orderbook,
orders: Orders,
positions: Positions,
collateral: Collateral,
};
interface TradeGridProps { interface TradeGridProps {
market: Market_market; market: Market_market;
@ -25,7 +42,7 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
<TradingViews.chart /> <TradingViews.chart />
</TradeGridChild> </TradeGridChild>
<TradeGridChild className="row-start-1 row-end-3"> <TradeGridChild className="row-start-1 row-end-3">
<TradingViews.ticket /> <TradingViews.ticket market={market} />
</TradeGridChild> </TradeGridChild>
<TradeGridChild className="row-start-1 row-end-3"> <TradeGridChild className="row-start-1 row-end-3">
<GridTabs group="trade"> <GridTabs group="trade">
@ -88,7 +105,7 @@ export const TradePanels = ({ market }: TradePanelsProps) => {
throw new Error(`No component for view: ${view}`); throw new Error(`No component for view: ${view}`);
} }
return <Component />; return <Component market={market} />;
}; };
return ( return (

View File

@ -48,16 +48,6 @@
"options": { "options": {
"lintFilePatterns": ["apps/trading/**/*.{ts,tsx,js,jsx}"] "lintFilePatterns": ["apps/trading/**/*.{ts,tsx,js,jsx}"]
} }
},
"generate": {
"builder": "@nrwl/workspace:run-commands",
"options": {
"commands": [
{
"command": "npx apollo client:codegen --config=apps/trading/apollo.config.js --target=typescript --globalTypesFile=apps/trading/__generated__/globalTypes.ts"
}
]
}
} }
}, },
"tags": [] "tags": []

View File

@ -14,5 +14,5 @@
"incremental": true "incremental": true
}, },
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "next-env.d.ts"], "include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "next-env.d.ts"],
"exclude": ["node_modules", "__generated__"] "exclude": ["node_modules"]
} }

12
libs/deal-ticket/.babelrc Normal file
View File

@ -0,0 +1,12 @@
{
"presets": [
[
"@nrwl/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}

View File

@ -0,0 +1,18 @@
{
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

View File

@ -0,0 +1,7 @@
# deal-ticket
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test deal-ticket` to execute the unit tests via [Jest](https://jestjs.io).

View File

@ -0,0 +1,9 @@
module.exports = {
displayName: 'deal-ticket',
preset: '../../jest.preset.js',
transform: {
'^.+\\.[tj]sx?$': 'babel-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/deal-ticket',
};

View File

@ -0,0 +1,4 @@
{
"name": "@vegaprotocol/deal-ticket",
"version": "0.0.1"
}

View File

@ -0,0 +1,43 @@
{
"root": "libs/deal-ticket",
"sourceRoot": "libs/deal-ticket/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nrwl/web:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/deal-ticket",
"tsConfig": "libs/deal-ticket/tsconfig.lib.json",
"project": "libs/deal-ticket/package.json",
"entryFile": "libs/deal-ticket/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/deal-ticket/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/deal-ticket/**/*.{ts,tsx,js,jsx}"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/deal-ticket"],
"options": {
"jestConfig": "libs/deal-ticket/jest.config.js",
"passWithNoTests": true
}
}
}
}

View File

@ -0,0 +1,38 @@
import { Button } from '@vegaprotocol/ui-toolkit';
interface ButtonRadioProps {
name: string;
options: Array<{ value: string; text: string }>;
currentOption: string | null;
onSelect: (option: string) => void;
}
export const ButtonRadio = ({
name,
options,
currentOption,
onSelect,
}: ButtonRadioProps) => {
return (
<div className="flex gap-8">
{options.map((option) => {
const isSelected = option.value === currentOption;
return (
<Button
onClick={() => onSelect(option.value)}
className="flex-1"
variant={isSelected ? 'accent' : undefined}
data-testid={
isSelected
? `${name}-${option.value}-selected`
: `${name}-${option.value}`
}
key={option.value}
>
{option.text}
</Button>
);
})}
</div>
);
};

View File

@ -0,0 +1,78 @@
import { FormGroup, Input } from '@vegaprotocol/ui-toolkit';
import { OrderTimeInForce } from '@vegaprotocol/wallet';
import { TransactionStatus } from './deal-ticket';
import { Market_market } from '@vegaprotocol/graphql';
import { ExpirySelector } from './expiry-selector';
import { SideSelector } from './side-selector';
import { SubmitButton } from './submit-button';
import { TimeInForceSelector } from './time-in-force-selector';
import { TypeSelector } from './type-selector';
import { Order } from './use-order-state';
interface DealTicketLimitProps {
order: Order;
updateOrder: (order: Partial<Order>) => void;
transactionStatus: TransactionStatus;
market: Market_market;
}
export const DealTicketLimit = ({
order,
updateOrder,
transactionStatus,
market,
}: DealTicketLimitProps) => {
return (
<>
<TypeSelector order={order} onSelect={(type) => updateOrder({ type })} />
<SideSelector order={order} onSelect={(side) => updateOrder({ side })} />
<div className="flex items-center gap-8">
<div className="flex-1">
<FormGroup label="Amount">
<Input
value={order.size}
onChange={(e) => updateOrder({ size: e.target.value })}
className="w-full"
type="number"
data-testid="order-size"
/>
</FormGroup>
</div>
<div>@</div>
<div className="flex-1">
<FormGroup
label={`Price (${market.tradableInstrument.instrument.product.quoteName})`}
labelAlign="right"
>
<Input
value={order.price}
onChange={(e) => updateOrder({ price: e.target.value })}
className="w-full"
type="number"
data-testid="order-price"
/>
</FormGroup>
</div>
</div>
<TimeInForceSelector
order={order}
onSelect={(timeInForce) => updateOrder({ timeInForce })}
/>
{order.timeInForce === OrderTimeInForce.GTT && (
<ExpirySelector
order={order}
onSelect={(date) => {
if (date) {
updateOrder({ expiration: date });
}
}}
/>
)}
<SubmitButton
transactionStatus={transactionStatus}
market={market}
order={order}
/>
</>
);
};

View File

@ -0,0 +1,63 @@
import { addDecimal } from '@vegaprotocol/react-helpers';
import { FormGroup, Input } from '@vegaprotocol/ui-toolkit';
import { Market_market } from '@vegaprotocol/graphql';
import { TransactionStatus } from './deal-ticket';
import { SideSelector } from './side-selector';
import { SubmitButton } from './submit-button';
import { TimeInForceSelector } from './time-in-force-selector';
import { TypeSelector } from './type-selector';
import { Order } from './use-order-state';
interface DealTicketMarketProps {
order: Order;
updateOrder: (order: Partial<Order>) => void;
transactionStatus: TransactionStatus;
market: Market_market;
}
export const DealTicketMarket = ({
order,
updateOrder,
transactionStatus,
market,
}: DealTicketMarketProps) => {
return (
<>
<TypeSelector order={order} onSelect={(type) => updateOrder({ type })} />
<SideSelector order={order} onSelect={(side) => updateOrder({ side })} />
<div className="flex items-center gap-8">
<div className="flex-1">
<FormGroup label="Amount">
<Input
value={order.size}
onChange={(e) => updateOrder({ size: e.target.value })}
className="w-full"
type="number"
data-testid="order-size"
/>
</FormGroup>
</div>
<div className="pt-4">@</div>
<div className="flex-1 pt-4" data-testid="last-price">
{market.depth.lastTrade ? (
<>
~{addDecimal(market.depth.lastTrade.price, market.decimalPlaces)}{' '}
{market.tradableInstrument.instrument.product.quoteName}
</>
) : (
'-'
)}
</div>
</div>
<TimeInForceSelector
order={order}
onSelect={(timeInForce) => updateOrder({ timeInForce })}
/>
<SubmitButton
transactionStatus={transactionStatus}
market={market}
order={order}
/>
</>
);
};

View File

@ -0,0 +1,141 @@
import '@testing-library/jest-dom';
import {
VegaWalletContext,
OrderTimeInForce,
OrderType,
} from '@vegaprotocol/wallet';
import { addDecimal } from '@vegaprotocol/react-helpers';
import { fireEvent, render, screen } from '@testing-library/react';
import { DealTicket, Market } from './deal-ticket';
import { Order } from './use-order-state';
const order: Order = {
type: OrderType.Market,
size: '100',
timeInForce: OrderTimeInForce.FOK,
side: null,
};
const market: Market = {
id: 'market-id',
decimalPlaces: 2,
tradingMode: 'Continuous',
state: 'Active',
tradableInstrument: {
instrument: {
product: {
quoteName: 'quote-name',
settlementAsset: {
id: 'asset-id',
symbol: 'asset-symbol',
name: 'asset-name',
},
},
},
},
depth: {
lastTrade: {
price: '100',
},
},
};
function generateJsx() {
return (
<VegaWalletContext.Provider value={{} as any}>
<DealTicket defaultOrder={order} market={market} />
</VegaWalletContext.Provider>
);
}
test('Deal ticket defaults', () => {
render(generateJsx());
// Assert defaults are used
expect(
screen.getByTestId(`order-type-${order.type}-selected`)
).toBeInTheDocument();
expect(
screen.queryByTestId('order-side-SIDE_BUY-selected')
).not.toBeInTheDocument();
expect(
screen.queryByTestId('order-side-SIDE_SELL-selected')
).not.toBeInTheDocument();
expect(screen.getByTestId('order-size')).toHaveDisplayValue(order.size);
expect(screen.getByTestId('order-tif')).toHaveValue(order.timeInForce);
// Assert last price is shown
expect(screen.getByTestId('last-price')).toHaveTextContent(
// eslint-disable-next-line
`~${addDecimal(market.depth.lastTrade!.price, market.decimalPlaces)} ${
market.tradableInstrument.instrument.product.quoteName
}`
);
});
test('Can edit deal ticket', () => {
render(generateJsx());
// Asssert changing values
fireEvent.click(screen.getByTestId('order-side-SIDE_BUY'));
expect(
screen.getByTestId('order-side-SIDE_BUY-selected')
).toBeInTheDocument();
fireEvent.change(screen.getByTestId('order-size'), {
target: { value: '200' },
});
expect(screen.getByTestId('order-size')).toHaveDisplayValue('200');
fireEvent.change(screen.getByTestId('order-tif'), {
target: { value: OrderTimeInForce.IOC },
});
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.IOC);
// Switch to limit order
fireEvent.click(screen.getByTestId('order-type-TYPE_LIMIT'));
// Assert price input shown with default value
expect(screen.getByTestId('order-price')).toHaveDisplayValue('0');
// Check all TIF options shown
expect(screen.getByTestId('order-tif').children).toHaveLength(
Object.keys(OrderTimeInForce).length
);
});
test('Handles TIF select box dependent on order type', () => {
render(generateJsx());
// Check only IOC and
expect(
Array.from(screen.getByTestId('order-tif').children).map(
(o) => o.textContent
)
).toEqual(['IOC', 'FOK']);
// Switch to limit order and check all TIF options shown
fireEvent.click(screen.getByTestId('order-type-TYPE_LIMIT'));
expect(screen.getByTestId('order-tif').children).toHaveLength(
Object.keys(OrderTimeInForce).length
);
// Change to GTC
fireEvent.change(screen.getByTestId('order-tif'), {
target: { value: OrderTimeInForce.GTC },
});
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.GTC);
// Switch back to market order and TIF should now be IOC
fireEvent.click(screen.getByTestId('order-type-TYPE_MARKET'));
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.IOC);
// Switch tif to FOK
fireEvent.change(screen.getByTestId('order-tif'), {
target: { value: OrderTimeInForce.FOK },
});
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.FOK);
// Change back to limit and check we are still on FOK
fireEvent.click(screen.getByTestId('order-type-TYPE_LIMIT'));
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.FOK);
});

View File

@ -0,0 +1,69 @@
import { OrderSide, OrderTimeInForce, OrderType } from '@vegaprotocol/wallet';
import { Market_market } from '@vegaprotocol/graphql';
import { FormEvent } from 'react';
import { Order, useOrderState } from './use-order-state';
import { DealTicketMarket } from './deal-ticket-market';
import { DealTicketLimit } from './deal-ticket-limit';
const DEFAULT_ORDER: Order = {
type: OrderType.Market,
side: OrderSide.Buy,
size: '1',
timeInForce: OrderTimeInForce.IOC,
};
// TODO: Consider using a generated type when we have a better solution for
// sharing the types from GQL
export type TransactionStatus = 'default' | 'pending';
export interface DealTicketProps {
market: Market_market;
submit: (order: Order) => void;
transactionStatus: TransactionStatus;
defaultOrder?: Order;
}
export const DealTicket = ({
market,
submit,
transactionStatus,
defaultOrder = DEFAULT_ORDER,
}: DealTicketProps) => {
const [order, updateOrder] = useOrderState(defaultOrder);
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
submit(order);
};
let ticket = null;
if (order.type === OrderType.Market) {
ticket = (
<DealTicketMarket
order={order}
updateOrder={updateOrder}
transactionStatus={transactionStatus}
market={market}
/>
);
} else if (order.type === OrderType.Limit) {
ticket = (
<DealTicketLimit
order={order}
updateOrder={updateOrder}
transactionStatus={transactionStatus}
market={market}
/>
);
} else {
throw new Error('Invalid ticket type');
}
return (
<form onSubmit={handleSubmit} className="px-4 py-8">
{ticket}
</form>
);
};

View File

@ -0,0 +1,26 @@
import { FormGroup, Input } from '@vegaprotocol/ui-toolkit';
import { Order } from './use-order-state';
import { formatForInput } from '@vegaprotocol/react-helpers';
interface ExpirySelectorProps {
order: Order;
onSelect: (expiration: Date | null) => void;
}
export const ExpirySelector = ({ order, onSelect }: ExpirySelectorProps) => {
const date = order.expiration ? new Date(order.expiration) : new Date();
const dateFormatted = formatForInput(date);
const minDate = formatForInput(date);
return (
<FormGroup label="Expiry time/date" labelFor="expiration">
<Input
id="expiration"
name="expiration"
type="datetime-local"
value={dateFormatted}
onChange={(e) => onSelect(new Date(e.target.value))}
min={minDate}
/>
</FormGroup>
);
};

View File

@ -0,0 +1,2 @@
export * from './deal-ticket';
export * from './use-order-state';

View File

@ -0,0 +1,25 @@
import { FormGroup } from '@vegaprotocol/ui-toolkit';
import { OrderSide } from '@vegaprotocol/wallet';
import { ButtonRadio } from './button-radio';
import { Order } from './use-order-state';
interface SideSelectorProps {
order: Order;
onSelect: (side: OrderSide) => void;
}
export const SideSelector = ({ order, onSelect }: SideSelectorProps) => {
return (
<FormGroup label="Direction">
<ButtonRadio
name="order-side"
options={Object.entries(OrderSide).map(([text, value]) => ({
text,
value,
}))}
currentOption={order.side}
onSelect={(value) => onSelect(value as OrderSide)}
/>
</FormGroup>
);
};

View File

@ -0,0 +1,78 @@
import { Button, InputError } from '@vegaprotocol/ui-toolkit';
import { OrderTimeInForce, OrderType } from '@vegaprotocol/wallet';
import { Market_market } from '@vegaprotocol/graphql';
import { useMemo } from 'react';
import { Order } from './use-order-state';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { TransactionStatus } from './deal-ticket';
interface SubmitButtonProps {
transactionStatus: TransactionStatus;
market: Market_market;
order: Order;
}
export const SubmitButton = ({
market,
transactionStatus,
order,
}: SubmitButtonProps) => {
const { keypair } = useVegaWallet();
const invalidText = useMemo(() => {
if (!keypair) {
return 'No public key selected';
}
if (keypair.tainted) {
return 'Selected public key has been tainted';
}
// TODO: Change these to use enums from @vegaprotocol/graphql
if (market.state !== 'Active') {
if (market.state === 'Suspended') {
return 'Market is currently suspended';
}
if (market.state === 'Proposed' || market.state === 'Pending') {
return 'Market is not active yet';
}
return 'Market is no longer active';
}
if (market.tradingMode !== 'Continuous') {
if (order.type === OrderType.Market) {
return 'Only limit orders are permitted when market is in auction';
}
if (
[
OrderTimeInForce.FOK,
OrderTimeInForce.IOC,
OrderTimeInForce.GFN,
].includes(order.timeInForce)
) {
return 'Only GTT, GTC and GFA are permitted when market is in auction';
}
}
return '';
}, [keypair, market, order]);
const disabled = transactionStatus === 'pending' || Boolean(invalidText);
return (
<>
<Button
className="w-full mb-8"
variant="primary"
type="submit"
disabled={disabled}
>
{transactionStatus === 'pending' ? 'Pending...' : 'Place order'}
</Button>
{invalidText && <InputError className="mb-8">{invalidText}</InputError>}
</>
);
};

View File

@ -0,0 +1,40 @@
import { FormGroup, Select } from '@vegaprotocol/ui-toolkit';
import { OrderTimeInForce, OrderType } from '@vegaprotocol/wallet';
import { Order } from './use-order-state';
interface TimeInForceSelectorProps {
order: Order;
onSelect: (tif: OrderTimeInForce) => void;
}
export const TimeInForceSelector = ({
order,
onSelect,
}: TimeInForceSelectorProps) => {
const options =
order.type === OrderType.Limit
? Object.entries(OrderTimeInForce)
: Object.entries(OrderTimeInForce).filter(
([key, value]) =>
value === OrderTimeInForce.FOK || value === OrderTimeInForce.IOC
);
return (
<FormGroup label="Time in force">
<Select
value={order.timeInForce}
onChange={(e) => onSelect(e.target.value as OrderTimeInForce)}
className="w-full"
data-testid="order-tif"
>
{options.map(([key, value]) => {
return (
<option key={key} value={value}>
{key}
</option>
);
})}
</Select>
</FormGroup>
);
};

View File

@ -0,0 +1,25 @@
import { FormGroup } from '@vegaprotocol/ui-toolkit';
import { OrderType } from '@vegaprotocol/wallet';
import { ButtonRadio } from './button-radio';
import { Order } from './use-order-state';
interface TypeSelectorProps {
order: Order;
onSelect: (type: OrderType) => void;
}
export const TypeSelector = ({ order, onSelect }: TypeSelectorProps) => {
return (
<FormGroup label="Order type">
<ButtonRadio
name="order-type"
options={Object.entries(OrderType).map(([text, value]) => ({
text,
value,
}))}
currentOption={order.type}
onSelect={(value) => onSelect(value as OrderType)}
/>
</FormGroup>
);
};

View File

@ -0,0 +1,78 @@
import { OrderSide, OrderTimeInForce, OrderType } from '@vegaprotocol/wallet';
import { useState, useCallback } from 'react';
export interface Order {
size: string;
type: OrderType;
timeInForce: OrderTimeInForce;
side: OrderSide | null;
price?: string;
expiration?: Date;
}
export type UpdateOrder = (order: Partial<Order>) => void;
export const useOrderState = (defaultOrder: Order): [Order, UpdateOrder] => {
const [order, setOrder] = useState<Order>(defaultOrder);
const updateOrder = useCallback((orderUpdate: Partial<Order>) => {
setOrder((curr) => {
// Type is switching to market so return new market order object with correct defaults
if (
orderUpdate.type === OrderType.Market &&
curr.type !== OrderType.Market
) {
// Check if provided TIF or current TIF is valid for a market order and default
// to IOC if its not
const isTifValid = (tif: OrderTimeInForce) => {
return tif === OrderTimeInForce.FOK || tif === OrderTimeInForce.IOC;
};
// Default
let timeInForce = OrderTimeInForce.IOC;
if (orderUpdate.timeInForce) {
if (isTifValid(orderUpdate.timeInForce)) {
timeInForce = orderUpdate.timeInForce;
}
} else {
if (isTifValid(curr.timeInForce)) {
timeInForce = curr.timeInForce;
}
}
return {
type: orderUpdate.type,
size: orderUpdate.size || curr.size,
side: orderUpdate.side || curr.side,
timeInForce,
price: undefined,
expiration: undefined,
};
}
// Type is switching to limit so return new order object with correct defaults
if (
orderUpdate.type === OrderType.Limit &&
curr.type !== OrderType.Limit
) {
return {
type: orderUpdate.type,
size: orderUpdate.size || curr.size,
side: orderUpdate.side || curr.side,
timeInForce: orderUpdate.timeInForce || curr.timeInForce,
price: orderUpdate.price || '0',
expiration: orderUpdate.expiration || undefined,
};
}
return {
...curr,
...orderUpdate,
};
});
}, []);
return [order, updateOrder];
};

View File

@ -0,0 +1,25 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@ -0,0 +1,22 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": [
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

View File

@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.test.ts",
"**/*.spec.ts",
"**/*.test.tsx",
"**/*.spec.tsx",
"**/*.test.js",
"**/*.spec.js",
"**/*.test.jsx",
"**/*.spec.jsx",
"**/*.d.ts"
]
}

12
libs/graphql/.babelrc Normal file
View File

@ -0,0 +1,12 @@
{
"presets": [
[
"@nrwl/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}

View File

@ -0,0 +1,18 @@
{
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*", "__generated__"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

7
libs/graphql/README.md Normal file
View File

@ -0,0 +1,7 @@
# graphql
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test graphql` to execute the unit tests via [Jest](https://jestjs.io).

View File

@ -4,5 +4,6 @@ module.exports = {
name: 'vega', name: 'vega',
url: process.env.NX_VEGA_URL, url: process.env.NX_VEGA_URL,
}, },
includes: ['../../{apps,lib}/**/*.{ts,tsx,js,jsx,graphql}'],
}, },
}; };

View File

@ -0,0 +1,9 @@
module.exports = {
displayName: 'graphql',
preset: '../../jest.preset.js',
transform: {
'^.+\\.[tj]sx?$': 'babel-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/graphql',
};

View File

@ -0,0 +1,4 @@
{
"name": "@vegaprotocol/graphql",
"version": "0.0.1"
}

53
libs/graphql/project.json Normal file
View File

@ -0,0 +1,53 @@
{
"root": "libs/graphql",
"sourceRoot": "libs/graphql/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nrwl/web:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/graphql",
"tsConfig": "libs/graphql/tsconfig.lib.json",
"project": "libs/graphql/package.json",
"entryFile": "libs/graphql/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/graphql/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/graphql/**/*.{ts,tsx,js,jsx}"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/graphql"],
"options": {
"jestConfig": "libs/graphql/jest.config.js",
"passWithNoTests": true
}
},
"generate": {
"builder": "@nrwl/workspace:run-commands",
"options": {
"commands": [
{
"command": "npx apollo client:codegen libs/graphql/src/__generated__ --config=libs/graphql/apollo.config.js --target=typescript --globalTypesFile=libs/graphql/src/__generated__/globalTypes.ts --outputFlat"
}
]
}
}
}
}

View File

@ -3,14 +3,14 @@
// @generated // @generated
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AccountType } from './../../../../__generated__/globalTypes'; import { AccountType } from "./globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: AssetsQuery // GraphQL query operation: AssetsQuery
// ==================================================== // ====================================================
export interface AssetsQuery_assets_source_ERC20 { export interface AssetsQuery_assets_source_ERC20 {
__typename: 'ERC20'; __typename: "ERC20";
/** /**
* The address of the erc20 contract * The address of the erc20 contract
*/ */
@ -18,19 +18,17 @@ export interface AssetsQuery_assets_source_ERC20 {
} }
export interface AssetsQuery_assets_source_BuiltinAsset { export interface AssetsQuery_assets_source_BuiltinAsset {
__typename: 'BuiltinAsset'; __typename: "BuiltinAsset";
/** /**
* Maximum amount that can be requested by a party through the built-in asset faucet at a time * Maximum amount that can be requested by a party through the built-in asset faucet at a time
*/ */
maxFaucetAmountMint: string; maxFaucetAmountMint: string;
} }
export type AssetsQuery_assets_source = export type AssetsQuery_assets_source = AssetsQuery_assets_source_ERC20 | AssetsQuery_assets_source_BuiltinAsset;
| AssetsQuery_assets_source_ERC20
| AssetsQuery_assets_source_BuiltinAsset;
export interface AssetsQuery_assets_infrastructureFeeAccount_market { export interface AssetsQuery_assets_infrastructureFeeAccount_market {
__typename: 'Market'; __typename: "Market";
/** /**
* Market ID * Market ID
*/ */
@ -38,7 +36,7 @@ export interface AssetsQuery_assets_infrastructureFeeAccount_market {
} }
export interface AssetsQuery_assets_infrastructureFeeAccount { export interface AssetsQuery_assets_infrastructureFeeAccount {
__typename: 'Account'; __typename: "Account";
/** /**
* Account type (General, Margin, etc) * Account type (General, Margin, etc)
*/ */
@ -54,7 +52,7 @@ export interface AssetsQuery_assets_infrastructureFeeAccount {
} }
export interface AssetsQuery_assets { export interface AssetsQuery_assets {
__typename: 'Asset'; __typename: "Asset";
/** /**
* The id of the asset * The id of the asset
*/ */
@ -75,10 +73,6 @@ export interface AssetsQuery_assets {
* The precision of the asset * The precision of the asset
*/ */
decimals: number; decimals: number;
/**
* The min stake to become an lp for any market using this asset for settlement
*/
minLpStake: string;
/** /**
* The origin source of the asset (e.g: an erc20 asset) * The origin source of the asset (e.g: an erc20 asset)
*/ */

View File

@ -8,7 +8,7 @@
// ==================================================== // ====================================================
export interface Guess_party { export interface Guess_party {
__typename: 'Party'; __typename: "Party";
/** /**
* Party identifier * Party identifier
*/ */
@ -16,7 +16,7 @@ export interface Guess_party {
} }
export interface Guess_market { export interface Guess_market {
__typename: 'Market'; __typename: "Market";
/** /**
* Market ID * Market ID
*/ */

150
libs/graphql/src/__generated__/Market.ts generated Normal file
View File

@ -0,0 +1,150 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { MarketState, MarketTradingMode } from "./globalTypes";
// ====================================================
// GraphQL query operation: Market
// ====================================================
export interface Market_market_tradableInstrument_instrument_product_settlementAsset {
__typename: "Asset";
/**
* The id of the asset
*/
id: string;
/**
* The symbol of the asset (e.g: GBP)
*/
symbol: string;
/**
* The full name of the asset (e.g: Great British Pound)
*/
name: string;
}
export interface Market_market_tradableInstrument_instrument_product {
__typename: "Future";
/**
* String representing the quote (e.g. BTCUSD -> USD is quote)
*/
quoteName: string;
/**
* The name of the asset (string)
*/
settlementAsset: Market_market_tradableInstrument_instrument_product_settlementAsset;
}
export interface Market_market_tradableInstrument_instrument {
__typename: "Instrument";
/**
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
*/
product: Market_market_tradableInstrument_instrument_product;
}
export interface Market_market_tradableInstrument {
__typename: "TradableInstrument";
/**
* An instance of or reference to a fully specified instrument.
*/
instrument: Market_market_tradableInstrument_instrument;
}
export interface Market_market_trades {
__typename: "Trade";
/**
* The hash of the trade data
*/
id: string;
/**
* The price of the trade (probably initially the passive order price, other determination algorithms are possible though) (uint64)
*/
price: string;
/**
* The number of contracts trades, will always be <= the remaining size of both orders immediately before the trade (uint64)
*/
size: string;
/**
* RFC3339Nano time for when the trade occurred
*/
createdAt: string;
}
export interface Market_market_depth_lastTrade {
__typename: "Trade";
/**
* The price of the trade (probably initially the passive order price, other determination algorithms are possible though) (uint64)
*/
price: string;
}
export interface Market_market_depth {
__typename: "MarketDepth";
/**
* Last trade for the given market (if available)
*/
lastTrade: Market_market_depth_lastTrade | null;
}
export interface Market_market {
__typename: "Market";
/**
* Market ID
*/
id: string;
/**
* Market full name
*/
name: string;
/**
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
* number denominated in the currency of the Market. (uint64)
*
* Examples:
* Currency Balance decimalPlaces Real Balance
* GBP 100 0 GBP 100
* GBP 100 2 GBP 1.00
* GBP 100 4 GBP 0.01
* GBP 1 4 GBP 0.0001 ( 0.01p )
*
* GBX (pence) 100 0 GBP 1.00 (100p )
* GBX (pence) 100 2 GBP 0.01 ( 1p )
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
*/
decimalPlaces: number;
/**
* Current state of the market
*/
state: MarketState;
/**
* Current mode of execution of the market
*/
tradingMode: MarketTradingMode;
/**
* An instance of or reference to a tradable instrument.
*/
tradableInstrument: Market_market_tradableInstrument;
/**
* Trades on a market
*/
trades: Market_market_trades[] | null;
/**
* Current depth on the order book for this market
*/
depth: Market_market_depth;
}
export interface Market {
/**
* An instrument that is trading on the VEGA network
*/
market: Market_market | null;
}
export interface MarketVariables {
marketId: string;
}

View File

@ -0,0 +1,46 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { MarketState, MarketTradingMode } from "./globalTypes";
// ====================================================
// GraphQL fragment: MarketDataFields
// ====================================================
export interface MarketDataFields_market {
__typename: "Market";
/**
* Market ID
*/
id: string;
/**
* Current state of the market
*/
state: MarketState;
/**
* Current mode of execution of the market
*/
tradingMode: MarketTradingMode;
}
export interface MarketDataFields {
__typename: "MarketData";
/**
* market id of the associated mark price
*/
market: MarketDataFields_market;
/**
* the highest price level on an order book for buy orders.
*/
bestBidPrice: string;
/**
* the lowest price level on an order book for offer orders.
*/
bestOfferPrice: string;
/**
* the mark price (actually an unsigned int)
*/
markPrice: string;
}

View File

@ -0,0 +1,53 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { MarketState, MarketTradingMode } from "./globalTypes";
// ====================================================
// GraphQL subscription operation: MarketDataSub
// ====================================================
export interface MarketDataSub_marketData_market {
__typename: "Market";
/**
* Market ID
*/
id: string;
/**
* Current state of the market
*/
state: MarketState;
/**
* Current mode of execution of the market
*/
tradingMode: MarketTradingMode;
}
export interface MarketDataSub_marketData {
__typename: "MarketData";
/**
* market id of the associated mark price
*/
market: MarketDataSub_marketData_market;
/**
* the highest price level on an order book for buy orders.
*/
bestBidPrice: string;
/**
* the lowest price level on an order book for offer orders.
*/
bestOfferPrice: string;
/**
* the mark price (actually an unsigned int)
*/
markPrice: string;
}
export interface MarketDataSub {
/**
* Subscribe to the mark price changes
*/
marketData: MarketDataSub_marketData;
}

126
libs/graphql/src/__generated__/Markets.ts generated Normal file
View File

@ -0,0 +1,126 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { MarketState, MarketTradingMode } from "./globalTypes";
// ====================================================
// GraphQL query operation: Markets
// ====================================================
export interface Markets_markets_data_market {
__typename: "Market";
/**
* Market ID
*/
id: string;
/**
* Current state of the market
*/
state: MarketState;
/**
* Current mode of execution of the market
*/
tradingMode: MarketTradingMode;
}
export interface Markets_markets_data {
__typename: "MarketData";
/**
* market id of the associated mark price
*/
market: Markets_markets_data_market;
/**
* the highest price level on an order book for buy orders.
*/
bestBidPrice: string;
/**
* the lowest price level on an order book for offer orders.
*/
bestOfferPrice: string;
/**
* the mark price (actually an unsigned int)
*/
markPrice: string;
}
export interface Markets_markets_tradableInstrument_instrument_product_settlementAsset {
__typename: "Asset";
/**
* The symbol of the asset (e.g: GBP)
*/
symbol: string;
}
export interface Markets_markets_tradableInstrument_instrument_product {
__typename: "Future";
/**
* The name of the asset (string)
*/
settlementAsset: Markets_markets_tradableInstrument_instrument_product_settlementAsset;
}
export interface Markets_markets_tradableInstrument_instrument {
__typename: "Instrument";
/**
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
*/
code: string;
/**
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
*/
product: Markets_markets_tradableInstrument_instrument_product;
}
export interface Markets_markets_tradableInstrument {
__typename: "TradableInstrument";
/**
* An instance of or reference to a fully specified instrument.
*/
instrument: Markets_markets_tradableInstrument_instrument;
}
export interface Markets_markets {
__typename: "Market";
/**
* Market ID
*/
id: string;
/**
* Market full name
*/
name: string;
/**
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
* number denominated in the currency of the Market. (uint64)
*
* Examples:
* Currency Balance decimalPlaces Real Balance
* GBP 100 0 GBP 100
* GBP 100 2 GBP 1.00
* GBP 100 4 GBP 0.01
* GBP 1 4 GBP 0.0001 ( 0.01p )
*
* GBX (pence) 100 0 GBP 1.00 (100p )
* GBX (pence) 100 2 GBP 0.01 ( 1p )
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
*/
decimalPlaces: number;
/**
* marketData for the given market
*/
data: Markets_markets_data | null;
/**
* An instance of or reference to a tradable instrument.
*/
tradableInstrument: Markets_markets_tradableInstrument;
}
export interface Markets {
/**
* One or more instruments that are trading on the VEGA network
*/
markets: Markets_markets[] | null;
}

View File

@ -3,19 +3,14 @@
// @generated // @generated
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { import { MarketTradingMode, MarketState, AccountType, AuctionTrigger } from "./globalTypes";
MarketTradingMode,
MarketState,
AccountType,
AuctionTrigger,
} from './../../../../__generated__/globalTypes';
// ==================================================== // ====================================================
// GraphQL query operation: MarketsQuery // GraphQL query operation: MarketsQuery
// ==================================================== // ====================================================
export interface MarketsQuery_markets_fees_factors { export interface MarketsQuery_markets_fees_factors {
__typename: 'FeeFactors'; __typename: "FeeFactors";
/** /**
* The factor applied to calculate MakerFees, a non-negative float * The factor applied to calculate MakerFees, a non-negative float
*/ */
@ -31,7 +26,7 @@ export interface MarketsQuery_markets_fees_factors {
} }
export interface MarketsQuery_markets_fees { export interface MarketsQuery_markets_fees {
__typename: 'Fees'; __typename: "Fees";
/** /**
* The factors used to calculate the different fees * The factors used to calculate the different fees
*/ */
@ -39,7 +34,7 @@ export interface MarketsQuery_markets_fees {
} }
export interface MarketsQuery_markets_tradableInstrument_instrument_metadata { export interface MarketsQuery_markets_tradableInstrument_instrument_metadata {
__typename: 'InstrumentMetadata'; __typename: "InstrumentMetadata";
/** /**
* An arbitrary list of tags to associated to associate to the Instrument (string list) * An arbitrary list of tags to associated to associate to the Instrument (string list)
*/ */
@ -47,7 +42,7 @@ export interface MarketsQuery_markets_tradableInstrument_instrument_metadata {
} }
export interface MarketsQuery_markets_tradableInstrument_instrument_product_settlementAsset_globalRewardPoolAccount { export interface MarketsQuery_markets_tradableInstrument_instrument_product_settlementAsset_globalRewardPoolAccount {
__typename: 'Account'; __typename: "Account";
/** /**
* Balance as string - current account balance (approx. as balances can be updated several times per second) * Balance as string - current account balance (approx. as balances can be updated several times per second)
*/ */
@ -55,7 +50,7 @@ export interface MarketsQuery_markets_tradableInstrument_instrument_product_sett
} }
export interface MarketsQuery_markets_tradableInstrument_instrument_product_settlementAsset { export interface MarketsQuery_markets_tradableInstrument_instrument_product_settlementAsset {
__typename: 'Asset'; __typename: "Asset";
/** /**
* The id of the asset * The id of the asset
*/ */
@ -79,11 +74,7 @@ export interface MarketsQuery_markets_tradableInstrument_instrument_product_sett
} }
export interface MarketsQuery_markets_tradableInstrument_instrument_product { export interface MarketsQuery_markets_tradableInstrument_instrument_product {
__typename: 'Future'; __typename: "Future";
/**
* RFC3339Nano maturity date of the product
*/
maturity: string;
/** /**
* The name of the asset (string) * The name of the asset (string)
*/ */
@ -91,7 +82,7 @@ export interface MarketsQuery_markets_tradableInstrument_instrument_product {
} }
export interface MarketsQuery_markets_tradableInstrument_instrument { export interface MarketsQuery_markets_tradableInstrument_instrument {
__typename: 'Instrument'; __typename: "Instrument";
/** /**
* Full and fairly descriptive name for the instrument * Full and fairly descriptive name for the instrument
*/ */
@ -101,7 +92,7 @@ export interface MarketsQuery_markets_tradableInstrument_instrument {
*/ */
metadata: MarketsQuery_markets_tradableInstrument_instrument_metadata; metadata: MarketsQuery_markets_tradableInstrument_instrument_metadata;
/** /**
* Uniquely identify an instrument accrods all instruments available on Vega (string) * Uniquely identify an instrument across all instruments available on Vega (string)
*/ */
id: string; id: string;
/** /**
@ -115,7 +106,7 @@ export interface MarketsQuery_markets_tradableInstrument_instrument {
} }
export interface MarketsQuery_markets_tradableInstrument_riskModel_LogNormalRiskModel_params { export interface MarketsQuery_markets_tradableInstrument_riskModel_LogNormalRiskModel_params {
__typename: 'LogNormalModelParams'; __typename: "LogNormalModelParams";
/** /**
* r parameter * r parameter
*/ */
@ -131,7 +122,7 @@ export interface MarketsQuery_markets_tradableInstrument_riskModel_LogNormalRisk
} }
export interface MarketsQuery_markets_tradableInstrument_riskModel_LogNormalRiskModel { export interface MarketsQuery_markets_tradableInstrument_riskModel_LogNormalRiskModel {
__typename: 'LogNormalRiskModel'; __typename: "LogNormalRiskModel";
/** /**
* Tau parameter of the risk model * Tau parameter of the risk model
*/ */
@ -147,7 +138,7 @@ export interface MarketsQuery_markets_tradableInstrument_riskModel_LogNormalRisk
} }
export interface MarketsQuery_markets_tradableInstrument_riskModel_SimpleRiskModel_params { export interface MarketsQuery_markets_tradableInstrument_riskModel_SimpleRiskModel_params {
__typename: 'SimpleRiskModelParams'; __typename: "SimpleRiskModelParams";
/** /**
* Risk factor for long * Risk factor for long
*/ */
@ -159,19 +150,17 @@ export interface MarketsQuery_markets_tradableInstrument_riskModel_SimpleRiskMod
} }
export interface MarketsQuery_markets_tradableInstrument_riskModel_SimpleRiskModel { export interface MarketsQuery_markets_tradableInstrument_riskModel_SimpleRiskModel {
__typename: 'SimpleRiskModel'; __typename: "SimpleRiskModel";
/** /**
* Params for the simple risk model * Params for the simple risk model
*/ */
params: MarketsQuery_markets_tradableInstrument_riskModel_SimpleRiskModel_params; params: MarketsQuery_markets_tradableInstrument_riskModel_SimpleRiskModel_params;
} }
export type MarketsQuery_markets_tradableInstrument_riskModel = export type MarketsQuery_markets_tradableInstrument_riskModel = MarketsQuery_markets_tradableInstrument_riskModel_LogNormalRiskModel | MarketsQuery_markets_tradableInstrument_riskModel_SimpleRiskModel;
| MarketsQuery_markets_tradableInstrument_riskModel_LogNormalRiskModel
| MarketsQuery_markets_tradableInstrument_riskModel_SimpleRiskModel;
export interface MarketsQuery_markets_tradableInstrument_marginCalculator_scalingFactors { export interface MarketsQuery_markets_tradableInstrument_marginCalculator_scalingFactors {
__typename: 'ScalingFactors'; __typename: "ScalingFactors";
/** /**
* the scaling factor that determines the margin level at which Vega has to search for more money * the scaling factor that determines the margin level at which Vega has to search for more money
*/ */
@ -187,7 +176,7 @@ export interface MarketsQuery_markets_tradableInstrument_marginCalculator_scalin
} }
export interface MarketsQuery_markets_tradableInstrument_marginCalculator { export interface MarketsQuery_markets_tradableInstrument_marginCalculator {
__typename: 'MarginCalculator'; __typename: "MarginCalculator";
/** /**
* The scaling factors that will be used for margin calculation * The scaling factors that will be used for margin calculation
*/ */
@ -195,7 +184,7 @@ export interface MarketsQuery_markets_tradableInstrument_marginCalculator {
} }
export interface MarketsQuery_markets_tradableInstrument { export interface MarketsQuery_markets_tradableInstrument {
__typename: 'TradableInstrument'; __typename: "TradableInstrument";
/** /**
* An instance of or reference to a fully specified instrument. * An instance of or reference to a fully specified instrument.
*/ */
@ -211,7 +200,7 @@ export interface MarketsQuery_markets_tradableInstrument {
} }
export interface MarketsQuery_markets_openingAuction { export interface MarketsQuery_markets_openingAuction {
__typename: 'AuctionDuration'; __typename: "AuctionDuration";
/** /**
* Duration of the auction in seconds * Duration of the auction in seconds
*/ */
@ -223,7 +212,7 @@ export interface MarketsQuery_markets_openingAuction {
} }
export interface MarketsQuery_markets_priceMonitoringSettings_parameters_triggers { export interface MarketsQuery_markets_priceMonitoringSettings_parameters_triggers {
__typename: 'PriceMonitoringTrigger'; __typename: "PriceMonitoringTrigger";
/** /**
* Price monitoring projection horizon τ in seconds (> 0). * Price monitoring projection horizon τ in seconds (> 0).
*/ */
@ -241,17 +230,15 @@ export interface MarketsQuery_markets_priceMonitoringSettings_parameters_trigger
} }
export interface MarketsQuery_markets_priceMonitoringSettings_parameters { export interface MarketsQuery_markets_priceMonitoringSettings_parameters {
__typename: 'PriceMonitoringParameters'; __typename: "PriceMonitoringParameters";
/** /**
* The list of triggers for this price monitoring * The list of triggers for this price monitoring
*/ */
triggers: triggers: MarketsQuery_markets_priceMonitoringSettings_parameters_triggers[] | null;
| MarketsQuery_markets_priceMonitoringSettings_parameters_triggers[]
| null;
} }
export interface MarketsQuery_markets_priceMonitoringSettings { export interface MarketsQuery_markets_priceMonitoringSettings {
__typename: 'PriceMonitoringSettings'; __typename: "PriceMonitoringSettings";
/** /**
* Specified a set of PriceMonitoringParameters to be use for price monitoring purposes * Specified a set of PriceMonitoringParameters to be use for price monitoring purposes
*/ */
@ -263,7 +250,7 @@ export interface MarketsQuery_markets_priceMonitoringSettings {
} }
export interface MarketsQuery_markets_liquidityMonitoringParameters_targetStakeParameters { export interface MarketsQuery_markets_liquidityMonitoringParameters_targetStakeParameters {
__typename: 'TargetStakeParameters'; __typename: "TargetStakeParameters";
/** /**
* Specifies length of time window expressed in seconds for target stake calculation * Specifies length of time window expressed in seconds for target stake calculation
*/ */
@ -275,7 +262,7 @@ export interface MarketsQuery_markets_liquidityMonitoringParameters_targetStakeP
} }
export interface MarketsQuery_markets_liquidityMonitoringParameters { export interface MarketsQuery_markets_liquidityMonitoringParameters {
__typename: 'LiquidityMonitoringParameters'; __typename: "LiquidityMonitoringParameters";
/** /**
* Specifies the triggering ratio for entering liquidity auction * Specifies the triggering ratio for entering liquidity auction
*/ */
@ -287,7 +274,7 @@ export interface MarketsQuery_markets_liquidityMonitoringParameters {
} }
export interface MarketsQuery_markets_proposal { export interface MarketsQuery_markets_proposal {
__typename: 'Proposal'; __typename: "Proposal";
/** /**
* Proposal ID that is filled by VEGA once proposal reaches the network * Proposal ID that is filled by VEGA once proposal reaches the network
*/ */
@ -295,7 +282,7 @@ export interface MarketsQuery_markets_proposal {
} }
export interface MarketsQuery_markets_accounts_asset { export interface MarketsQuery_markets_accounts_asset {
__typename: 'Asset'; __typename: "Asset";
/** /**
* The id of the asset * The id of the asset
*/ */
@ -307,7 +294,7 @@ export interface MarketsQuery_markets_accounts_asset {
} }
export interface MarketsQuery_markets_accounts { export interface MarketsQuery_markets_accounts {
__typename: 'Account'; __typename: "Account";
/** /**
* Asset, the 'currency' * Asset, the 'currency'
*/ */
@ -323,7 +310,7 @@ export interface MarketsQuery_markets_accounts {
} }
export interface MarketsQuery_markets_data_priceMonitoringBounds_trigger { export interface MarketsQuery_markets_data_priceMonitoringBounds_trigger {
__typename: 'PriceMonitoringTrigger'; __typename: "PriceMonitoringTrigger";
/** /**
* Price monitoring auction extension duration in seconds should the price * Price monitoring auction extension duration in seconds should the price
* breach it's theoretical level over the specified horizon at the specified * breach it's theoretical level over the specified horizon at the specified
@ -337,7 +324,7 @@ export interface MarketsQuery_markets_data_priceMonitoringBounds_trigger {
} }
export interface MarketsQuery_markets_data_priceMonitoringBounds { export interface MarketsQuery_markets_data_priceMonitoringBounds {
__typename: 'PriceMonitoringBounds'; __typename: "PriceMonitoringBounds";
/** /**
* Minimum price that isn't currently breaching the specified price monitoring trigger * Minimum price that isn't currently breaching the specified price monitoring trigger
*/ */
@ -357,7 +344,7 @@ export interface MarketsQuery_markets_data_priceMonitoringBounds {
} }
export interface MarketsQuery_markets_data_liquidityProviderFeeShare_party { export interface MarketsQuery_markets_data_liquidityProviderFeeShare_party {
__typename: 'Party'; __typename: "Party";
/** /**
* Party identifier * Party identifier
*/ */
@ -365,7 +352,7 @@ export interface MarketsQuery_markets_data_liquidityProviderFeeShare_party {
} }
export interface MarketsQuery_markets_data_liquidityProviderFeeShare { export interface MarketsQuery_markets_data_liquidityProviderFeeShare {
__typename: 'LiquidityProviderFeeShare'; __typename: "LiquidityProviderFeeShare";
/** /**
* The liquidity provider party id * The liquidity provider party id
*/ */
@ -375,15 +362,15 @@ export interface MarketsQuery_markets_data_liquidityProviderFeeShare {
*/ */
equityLikeShare: string; equityLikeShare: string;
/** /**
* the average entry valuation of the liqidity provider for the market * the average entry valuation of the liquidity provider for the market
*/ */
averageEntryValuation: string; averageEntryValuation: string;
} }
export interface MarketsQuery_markets_data { export interface MarketsQuery_markets_data {
__typename: 'MarketData'; __typename: "MarketData";
/** /**
* the mark price (actually an unsgined int) * the mark price (actually an unsigned int)
*/ */
markPrice: string; markPrice: string;
/** /**
@ -427,7 +414,7 @@ export interface MarketsQuery_markets_data {
*/ */
staticMidPrice: string; staticMidPrice: string;
/** /**
* RFC3339Nano time at which this market price was releavant * RFC3339Nano time at which this market price was relevant
*/ */
timestamp: string; timestamp: string;
/** /**
@ -469,9 +456,7 @@ export interface MarketsQuery_markets_data {
/** /**
* A list of valid price ranges per associated trigger * A list of valid price ranges per associated trigger
*/ */
priceMonitoringBounds: priceMonitoringBounds: MarketsQuery_markets_data_priceMonitoringBounds[] | null;
| MarketsQuery_markets_data_priceMonitoringBounds[]
| null;
/** /**
* the market value proxy * the market value proxy
*/ */
@ -479,13 +464,11 @@ export interface MarketsQuery_markets_data {
/** /**
* the equity like share of liquidity fee for each liquidity provider * the equity like share of liquidity fee for each liquidity provider
*/ */
liquidityProviderFeeShare: liquidityProviderFeeShare: MarketsQuery_markets_data_liquidityProviderFeeShare[] | null;
| MarketsQuery_markets_data_liquidityProviderFeeShare[]
| null;
} }
export interface MarketsQuery_markets { export interface MarketsQuery_markets {
__typename: 'Market'; __typename: "Market";
/** /**
* Market ID * Market ID
*/ */

View File

@ -3,14 +3,14 @@
// @generated // @generated
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { NodeStatus } from './../../../../__generated__/globalTypes'; import { NodeStatus } from "./globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: NodesQuery // GraphQL query operation: NodesQuery
// ==================================================== // ====================================================
export interface NodesQuery_nodes_epochData { export interface NodesQuery_nodes_epochData {
__typename: 'EpochData'; __typename: "EpochData";
/** /**
* Total number of epochs since node was created * Total number of epochs since node was created
*/ */
@ -26,7 +26,7 @@ export interface NodesQuery_nodes_epochData {
} }
export interface NodesQuery_nodes { export interface NodesQuery_nodes {
__typename: 'Node'; __typename: "Node";
/** /**
* The node url eg n01.vega.xyz * The node url eg n01.vega.xyz
*/ */
@ -71,8 +71,6 @@ export interface NodesQuery_nodes {
pendingStake: string; pendingStake: string;
epochData: NodesQuery_nodes_epochData | null; epochData: NodesQuery_nodes_epochData | null;
status: NodeStatus; status: NodeStatus;
score: string;
normalisedScore: string;
} }
export interface NodesQuery { export interface NodesQuery {

View File

@ -0,0 +1,91 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { BusEventType, OrderType, OrderStatus, OrderRejectionReason } from "./globalTypes";
// ====================================================
// GraphQL subscription operation: OrderEvent
// ====================================================
export interface OrderEvent_busEvents_event_TimeUpdate {
__typename: "TimeUpdate" | "MarketEvent" | "TransferResponses" | "PositionResolution" | "Trade" | "Account" | "Party" | "MarginLevels" | "Proposal" | "Vote" | "MarketData" | "NodeSignature" | "LossSocialization" | "SettlePosition" | "Market" | "Asset" | "MarketTick" | "SettleDistressed" | "AuctionEvent" | "RiskFactor" | "Deposit" | "Withdrawal" | "OracleSpec" | "LiquidityProvision";
}
export interface OrderEvent_busEvents_event_Order_market {
__typename: "Market";
/**
* Market full name
*/
name: string;
}
export interface OrderEvent_busEvents_event_Order {
__typename: "Order";
/**
* Type the order type (defaults to PARTY)
*/
type: OrderType | null;
/**
* Hash of the order data
*/
id: string;
/**
* The status of an order, for example 'Active'
*/
status: OrderStatus;
/**
* Reason for the order to be rejected
*/
rejectionReason: OrderRejectionReason | null;
/**
* RFC3339Nano formatted date and time for when the order was created (timestamp)
*/
createdAt: string;
/**
* Total number of contracts that may be bought or sold (immutable) (uint64)
*/
size: string;
/**
* The worst price the order will trade at (e.g. buy for price or less, sell for price or more) (uint64)
*/
price: string;
/**
* The market the order is trading on (probably stored internally as a hash of the market details)
*/
market: OrderEvent_busEvents_event_Order_market | null;
}
export type OrderEvent_busEvents_event = OrderEvent_busEvents_event_TimeUpdate | OrderEvent_busEvents_event_Order;
export interface OrderEvent_busEvents {
__typename: "BusEvent";
/**
* the id for this event
*/
eventId: string;
/**
* the block hash
*/
block: string;
/**
* the type of event we're dealing with
*/
type: BusEventType;
/**
* the payload - the wrapped event
*/
event: OrderEvent_busEvents_event;
}
export interface OrderEvent {
/**
* Subscribe to event data from the event bus
*/
busEvents: OrderEvent_busEvents[] | null;
}
export interface OrderEventVariables {
partyId: string;
}

View File

@ -3,14 +3,14 @@
// @generated // @generated
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AccountType } from '../../../../../__generated__/globalTypes'; import { AccountType } from "./globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: PartyAssetsQuery // GraphQL query operation: PartyAssetsQuery
// ==================================================== // ====================================================
export interface PartyAssetsQuery_party_delegations_node { export interface PartyAssetsQuery_party_delegations_node {
__typename: 'Node'; __typename: "Node";
/** /**
* The node url eg n01.vega.xyz * The node url eg n01.vega.xyz
*/ */
@ -19,7 +19,7 @@ export interface PartyAssetsQuery_party_delegations_node {
} }
export interface PartyAssetsQuery_party_delegations { export interface PartyAssetsQuery_party_delegations {
__typename: 'Delegation'; __typename: "Delegation";
/** /**
* Amount delegated * Amount delegated
*/ */
@ -35,7 +35,7 @@ export interface PartyAssetsQuery_party_delegations {
} }
export interface PartyAssetsQuery_party_stake { export interface PartyAssetsQuery_party_stake {
__typename: 'PartyStake'; __typename: "PartyStake";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
@ -43,23 +43,21 @@ export interface PartyAssetsQuery_party_stake {
} }
export interface PartyAssetsQuery_party_accounts_asset_source_BuiltinAsset { export interface PartyAssetsQuery_party_accounts_asset_source_BuiltinAsset {
__typename: 'BuiltinAsset'; __typename: "BuiltinAsset";
} }
export interface PartyAssetsQuery_party_accounts_asset_source_ERC20 { export interface PartyAssetsQuery_party_accounts_asset_source_ERC20 {
__typename: 'ERC20'; __typename: "ERC20";
/** /**
* The address of the erc20 contract * The address of the erc20 contract
*/ */
contractAddress: string; contractAddress: string;
} }
export type PartyAssetsQuery_party_accounts_asset_source = export type PartyAssetsQuery_party_accounts_asset_source = PartyAssetsQuery_party_accounts_asset_source_BuiltinAsset | PartyAssetsQuery_party_accounts_asset_source_ERC20;
| PartyAssetsQuery_party_accounts_asset_source_BuiltinAsset
| PartyAssetsQuery_party_accounts_asset_source_ERC20;
export interface PartyAssetsQuery_party_accounts_asset { export interface PartyAssetsQuery_party_accounts_asset {
__typename: 'Asset'; __typename: "Asset";
/** /**
* The full name of the asset (e.g: Great British Pound) * The full name of the asset (e.g: Great British Pound)
*/ */
@ -83,7 +81,7 @@ export interface PartyAssetsQuery_party_accounts_asset {
} }
export interface PartyAssetsQuery_party_accounts { export interface PartyAssetsQuery_party_accounts {
__typename: 'Account'; __typename: "Account";
/** /**
* Asset, the 'currency' * Asset, the 'currency'
*/ */
@ -99,14 +97,14 @@ export interface PartyAssetsQuery_party_accounts {
} }
export interface PartyAssetsQuery_party { export interface PartyAssetsQuery_party {
__typename: 'Party'; __typename: "Party";
/** /**
* Party identifier * Party identifier
*/ */
id: string; id: string;
delegations: PartyAssetsQuery_party_delegations[] | null; delegations: PartyAssetsQuery_party_delegations[] | null;
/** /**
* The staking informations for this Party * The staking information for this Party
*/ */
stake: PartyAssetsQuery_party_stake; stake: PartyAssetsQuery_party_stake;
/** /**
@ -123,5 +121,5 @@ export interface PartyAssetsQuery {
} }
export interface PartyAssetsQueryVariables { export interface PartyAssetsQueryVariables {
partyId: string | undefined; partyId: string;
} }

View File

@ -3,26 +3,26 @@
// @generated // @generated
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { import { ProposalState, ProposalRejectionReason, VoteValue } from "./globalTypes";
ProposalState,
ProposalRejectionReason,
VoteValue,
} from './../../../../__generated__/globalTypes';
// ==================================================== // ====================================================
// GraphQL query operation: ProposalsQuery // GraphQL query operation: ProposalsQuery
// ==================================================== // ====================================================
export interface ProposalsQuery_proposals_party { export interface ProposalsQuery_proposals_party {
__typename: 'Party'; __typename: "Party";
/** /**
* Party identifier * Party identifier
*/ */
id: string; id: string;
} }
export interface ProposalsQuery_proposals_terms_change_NewFreeform {
__typename: "NewFreeform";
}
export interface ProposalsQuery_proposals_terms_change_NewMarket_instrument { export interface ProposalsQuery_proposals_terms_change_NewMarket_instrument {
__typename: 'InstrumentConfiguration'; __typename: "InstrumentConfiguration";
/** /**
* Full and fairly descriptive name for the instrument * Full and fairly descriptive name for the instrument
*/ */
@ -30,7 +30,7 @@ export interface ProposalsQuery_proposals_terms_change_NewMarket_instrument {
} }
export interface ProposalsQuery_proposals_terms_change_NewMarket { export interface ProposalsQuery_proposals_terms_change_NewMarket {
__typename: 'NewMarket'; __typename: "NewMarket";
/** /**
* New market instrument configuration * New market instrument configuration
*/ */
@ -38,12 +38,12 @@ export interface ProposalsQuery_proposals_terms_change_NewMarket {
} }
export interface ProposalsQuery_proposals_terms_change_UpdateMarket { export interface ProposalsQuery_proposals_terms_change_UpdateMarket {
__typename: 'UpdateMarket'; __typename: "UpdateMarket";
marketId: string; marketId: string;
} }
export interface ProposalsQuery_proposals_terms_change_NewAsset_source_BuiltinAsset { export interface ProposalsQuery_proposals_terms_change_NewAsset_source_BuiltinAsset {
__typename: 'BuiltinAsset'; __typename: "BuiltinAsset";
/** /**
* Maximum amount that can be requested by a party through the built-in asset faucet at a time * Maximum amount that can be requested by a party through the built-in asset faucet at a time
*/ */
@ -51,19 +51,17 @@ export interface ProposalsQuery_proposals_terms_change_NewAsset_source_BuiltinAs
} }
export interface ProposalsQuery_proposals_terms_change_NewAsset_source_ERC20 { export interface ProposalsQuery_proposals_terms_change_NewAsset_source_ERC20 {
__typename: 'ERC20'; __typename: "ERC20";
/** /**
* The address of the erc20 contract * The address of the erc20 contract
*/ */
contractAddress: string; contractAddress: string;
} }
export type ProposalsQuery_proposals_terms_change_NewAsset_source = export type ProposalsQuery_proposals_terms_change_NewAsset_source = ProposalsQuery_proposals_terms_change_NewAsset_source_BuiltinAsset | ProposalsQuery_proposals_terms_change_NewAsset_source_ERC20;
| ProposalsQuery_proposals_terms_change_NewAsset_source_BuiltinAsset
| ProposalsQuery_proposals_terms_change_NewAsset_source_ERC20;
export interface ProposalsQuery_proposals_terms_change_NewAsset { export interface ProposalsQuery_proposals_terms_change_NewAsset {
__typename: 'NewAsset'; __typename: "NewAsset";
/** /**
* The symbol of the asset (e.g: GBP) * The symbol of the asset (e.g: GBP)
*/ */
@ -75,7 +73,7 @@ export interface ProposalsQuery_proposals_terms_change_NewAsset {
} }
export interface ProposalsQuery_proposals_terms_change_UpdateNetworkParameter_networkParameter { export interface ProposalsQuery_proposals_terms_change_UpdateNetworkParameter_networkParameter {
__typename: 'NetworkParameter'; __typename: "NetworkParameter";
/** /**
* The name of the network parameter * The name of the network parameter
*/ */
@ -87,18 +85,14 @@ export interface ProposalsQuery_proposals_terms_change_UpdateNetworkParameter_ne
} }
export interface ProposalsQuery_proposals_terms_change_UpdateNetworkParameter { export interface ProposalsQuery_proposals_terms_change_UpdateNetworkParameter {
__typename: 'UpdateNetworkParameter'; __typename: "UpdateNetworkParameter";
networkParameter: ProposalsQuery_proposals_terms_change_UpdateNetworkParameter_networkParameter; networkParameter: ProposalsQuery_proposals_terms_change_UpdateNetworkParameter_networkParameter;
} }
export type ProposalsQuery_proposals_terms_change = export type ProposalsQuery_proposals_terms_change = ProposalsQuery_proposals_terms_change_NewFreeform | ProposalsQuery_proposals_terms_change_NewMarket | ProposalsQuery_proposals_terms_change_UpdateMarket | ProposalsQuery_proposals_terms_change_NewAsset | ProposalsQuery_proposals_terms_change_UpdateNetworkParameter;
| ProposalsQuery_proposals_terms_change_NewMarket
| ProposalsQuery_proposals_terms_change_UpdateMarket
| ProposalsQuery_proposals_terms_change_NewAsset
| ProposalsQuery_proposals_terms_change_UpdateNetworkParameter;
export interface ProposalsQuery_proposals_terms { export interface ProposalsQuery_proposals_terms {
__typename: 'ProposalTerms'; __typename: "ProposalTerms";
/** /**
* RFC3339Nano time and date when voting closes for this proposal. * RFC3339Nano time and date when voting closes for this proposal.
* Constrained by "minClose" and "maxClose" network parameters. * Constrained by "minClose" and "maxClose" network parameters.
@ -116,7 +110,7 @@ export interface ProposalsQuery_proposals_terms {
} }
export interface ProposalsQuery_proposals_votes_yes_votes_party_stake { export interface ProposalsQuery_proposals_votes_yes_votes_party_stake {
__typename: 'PartyStake'; __typename: "PartyStake";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
@ -124,19 +118,19 @@ export interface ProposalsQuery_proposals_votes_yes_votes_party_stake {
} }
export interface ProposalsQuery_proposals_votes_yes_votes_party { export interface ProposalsQuery_proposals_votes_yes_votes_party {
__typename: 'Party'; __typename: "Party";
/** /**
* Party identifier * Party identifier
*/ */
id: string; id: string;
/** /**
* The staking informations for this Party * The staking information for this Party
*/ */
stake: ProposalsQuery_proposals_votes_yes_votes_party_stake; stake: ProposalsQuery_proposals_votes_yes_votes_party_stake;
} }
export interface ProposalsQuery_proposals_votes_yes_votes { export interface ProposalsQuery_proposals_votes_yes_votes {
__typename: 'Vote'; __typename: "Vote";
/** /**
* The vote value cast * The vote value cast
*/ */
@ -152,7 +146,7 @@ export interface ProposalsQuery_proposals_votes_yes_votes {
} }
export interface ProposalsQuery_proposals_votes_yes { export interface ProposalsQuery_proposals_votes_yes {
__typename: 'ProposalVoteSide'; __typename: "ProposalVoteSide";
/** /**
* Total tokens of governance token from the votes casted for this side * Total tokens of governance token from the votes casted for this side
*/ */
@ -168,7 +162,7 @@ export interface ProposalsQuery_proposals_votes_yes {
} }
export interface ProposalsQuery_proposals_votes_no_votes_party_stake { export interface ProposalsQuery_proposals_votes_no_votes_party_stake {
__typename: 'PartyStake'; __typename: "PartyStake";
/** /**
* The stake currently available for the party * The stake currently available for the party
*/ */
@ -176,19 +170,19 @@ export interface ProposalsQuery_proposals_votes_no_votes_party_stake {
} }
export interface ProposalsQuery_proposals_votes_no_votes_party { export interface ProposalsQuery_proposals_votes_no_votes_party {
__typename: 'Party'; __typename: "Party";
/** /**
* Party identifier * Party identifier
*/ */
id: string; id: string;
/** /**
* The staking informations for this Party * The staking information for this Party
*/ */
stake: ProposalsQuery_proposals_votes_no_votes_party_stake; stake: ProposalsQuery_proposals_votes_no_votes_party_stake;
} }
export interface ProposalsQuery_proposals_votes_no_votes { export interface ProposalsQuery_proposals_votes_no_votes {
__typename: 'Vote'; __typename: "Vote";
/** /**
* The vote value cast * The vote value cast
*/ */
@ -204,7 +198,7 @@ export interface ProposalsQuery_proposals_votes_no_votes {
} }
export interface ProposalsQuery_proposals_votes_no { export interface ProposalsQuery_proposals_votes_no {
__typename: 'ProposalVoteSide'; __typename: "ProposalVoteSide";
/** /**
* Total tokens of governance token from the votes casted for this side * Total tokens of governance token from the votes casted for this side
*/ */
@ -220,7 +214,7 @@ export interface ProposalsQuery_proposals_votes_no {
} }
export interface ProposalsQuery_proposals_votes { export interface ProposalsQuery_proposals_votes {
__typename: 'ProposalVotes'; __typename: "ProposalVotes";
/** /**
* Yes votes cast for this proposal * Yes votes cast for this proposal
*/ */
@ -232,7 +226,7 @@ export interface ProposalsQuery_proposals_votes {
} }
export interface ProposalsQuery_proposals { export interface ProposalsQuery_proposals {
__typename: 'Proposal'; __typename: "Proposal";
/** /**
* Proposal ID that is filled by VEGA once proposal reaches the network * Proposal ID that is filled by VEGA once proposal reaches the network
*/ */

View File

@ -0,0 +1,234 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
//==============================================================
// START Enums and Input Objects
//==============================================================
/**
* The various account types we have (used by collateral)
*/
export enum AccountType {
Bond = "Bond",
External = "External",
FeeInfrastructure = "FeeInfrastructure",
FeeLiquidity = "FeeLiquidity",
FeeMaker = "FeeMaker",
General = "General",
GlobalInsurance = "GlobalInsurance",
GlobalReward = "GlobalReward",
Insurance = "Insurance",
LockWithdraw = "LockWithdraw",
Margin = "Margin",
PendingTransfers = "PendingTransfers",
RewardLpReceivedFees = "RewardLpReceivedFees",
RewardMakerReceivedFees = "RewardMakerReceivedFees",
RewardMarketProposers = "RewardMarketProposers",
RewardTakerPaidFees = "RewardTakerPaidFees",
Settlement = "Settlement",
}
export enum AuctionTrigger {
Batch = "Batch",
Liquidity = "Liquidity",
Opening = "Opening",
Price = "Price",
Unspecified = "Unspecified",
}
export enum BusEventType {
Account = "Account",
Asset = "Asset",
Auction = "Auction",
Deposit = "Deposit",
LiquidityProvision = "LiquidityProvision",
LossSocialization = "LossSocialization",
MarginLevels = "MarginLevels",
Market = "Market",
MarketCreated = "MarketCreated",
MarketData = "MarketData",
MarketTick = "MarketTick",
MarketUpdated = "MarketUpdated",
NodeSignature = "NodeSignature",
OracleSpec = "OracleSpec",
Order = "Order",
Party = "Party",
PositionResolution = "PositionResolution",
Proposal = "Proposal",
RiskFactor = "RiskFactor",
SettleDistressed = "SettleDistressed",
SettlePosition = "SettlePosition",
TimeUpdate = "TimeUpdate",
Trade = "Trade",
TransferResponses = "TransferResponses",
Vote = "Vote",
Withdrawal = "Withdrawal",
}
/**
* The current state of a market
*/
export enum MarketState {
Active = "Active",
Cancelled = "Cancelled",
Closed = "Closed",
Pending = "Pending",
Proposed = "Proposed",
Rejected = "Rejected",
Settled = "Settled",
Suspended = "Suspended",
TradingTerminated = "TradingTerminated",
}
/**
* What market trading mode are we in
*/
export enum MarketTradingMode {
BatchAuction = "BatchAuction",
Continuous = "Continuous",
MonitoringAuction = "MonitoringAuction",
OpeningAuction = "OpeningAuction",
}
export enum NodeStatus {
NonValidator = "NonValidator",
Validator = "Validator",
}
/**
* Reason for the order being rejected by the core node
*/
export enum OrderRejectionReason {
AmendToGTTWithoutExpiryAt = "AmendToGTTWithoutExpiryAt",
CannotAmendFromGFAOrGFN = "CannotAmendFromGFAOrGFN",
CannotAmendPeggedOrderDetailsOnNonPeggedOrder = "CannotAmendPeggedOrderDetailsOnNonPeggedOrder",
CannotAmendToFOKOrIOC = "CannotAmendToFOKOrIOC",
CannotAmendToGFAOrGFN = "CannotAmendToGFAOrGFN",
EditNotAllowed = "EditNotAllowed",
ExpiryAtBeforeCreatedAt = "ExpiryAtBeforeCreatedAt",
FOKOrderDuringAuction = "FOKOrderDuringAuction",
GFAOrderDuringContinuousTrading = "GFAOrderDuringContinuousTrading",
GFNOrderDuringAuction = "GFNOrderDuringAuction",
GTCWithExpiryAtNotValid = "GTCWithExpiryAtNotValid",
IOCOrderDuringAuction = "IOCOrderDuringAuction",
InsufficientAssetBalance = "InsufficientAssetBalance",
InsufficientFundsToPayFees = "InsufficientFundsToPayFees",
InternalError = "InternalError",
InvalidExpirationTime = "InvalidExpirationTime",
InvalidMarketId = "InvalidMarketId",
InvalidMarketType = "InvalidMarketType",
InvalidOrderId = "InvalidOrderId",
InvalidOrderReference = "InvalidOrderReference",
InvalidPartyId = "InvalidPartyId",
InvalidPersistence = "InvalidPersistence",
InvalidRemainingSize = "InvalidRemainingSize",
InvalidSize = "InvalidSize",
InvalidTimeInForce = "InvalidTimeInForce",
InvalidType = "InvalidType",
MarginCheckFailed = "MarginCheckFailed",
MarketClosed = "MarketClosed",
MissingGeneralAccount = "MissingGeneralAccount",
NonPersistentOrderExceedsPriceBounds = "NonPersistentOrderExceedsPriceBounds",
OrderAmendFailure = "OrderAmendFailure",
OrderNotFound = "OrderNotFound",
OrderOutOfSequence = "OrderOutOfSequence",
OrderRemovalFailure = "OrderRemovalFailure",
PeggedOrderBuyCannotReferenceBestAskPrice = "PeggedOrderBuyCannotReferenceBestAskPrice",
PeggedOrderMustBeGTTOrGTC = "PeggedOrderMustBeGTTOrGTC",
PeggedOrderMustBeLimitOrder = "PeggedOrderMustBeLimitOrder",
PeggedOrderOffsetMustBeGreaterOrEqualToZero = "PeggedOrderOffsetMustBeGreaterOrEqualToZero",
PeggedOrderOffsetMustBeGreaterThanZero = "PeggedOrderOffsetMustBeGreaterThanZero",
PeggedOrderSellCannotReferenceBestBidPrice = "PeggedOrderSellCannotReferenceBestBidPrice",
PeggedOrderWithoutReferencePrice = "PeggedOrderWithoutReferencePrice",
SelfTrading = "SelfTrading",
TimeFailure = "TimeFailure",
UnableToAmendPeggedOrderPrice = "UnableToAmendPeggedOrderPrice",
UnableToRepricePeggedOrder = "UnableToRepricePeggedOrder",
}
/**
* Valid order statuses, these determine several states for an order that cannot be expressed with other fields in Order.
*/
export enum OrderStatus {
Active = "Active",
Cancelled = "Cancelled",
Expired = "Expired",
Filled = "Filled",
Parked = "Parked",
PartiallyFilled = "PartiallyFilled",
Rejected = "Rejected",
Stopped = "Stopped",
}
export enum OrderType {
Limit = "Limit",
Market = "Market",
Network = "Network",
}
/**
* Reason for the proposal being rejected by the core node
*/
export enum ProposalRejectionReason {
CloseTimeTooLate = "CloseTimeTooLate",
CloseTimeTooSoon = "CloseTimeTooSoon",
CouldNotInstantiateMarket = "CouldNotInstantiateMarket",
EnactTimeTooLate = "EnactTimeTooLate",
EnactTimeTooSoon = "EnactTimeTooSoon",
IncompatibleTimestamps = "IncompatibleTimestamps",
InsufficientTokens = "InsufficientTokens",
InvalidAsset = "InvalidAsset",
InvalidAssetDetails = "InvalidAssetDetails",
InvalidFeeAmount = "InvalidFeeAmount",
InvalidFutureMaturityTimestamp = "InvalidFutureMaturityTimestamp",
InvalidFutureProduct = "InvalidFutureProduct",
InvalidInstrumentSecurity = "InvalidInstrumentSecurity",
InvalidRiskParameter = "InvalidRiskParameter",
InvalidShape = "InvalidShape",
MajorityThresholdNotReached = "MajorityThresholdNotReached",
MarketMissingLiquidityCommitment = "MarketMissingLiquidityCommitment",
MissingBuiltinAssetField = "MissingBuiltinAssetField",
MissingCommitmentAmount = "MissingCommitmentAmount",
MissingERC20ContractAddress = "MissingERC20ContractAddress",
NetworkParameterInvalidKey = "NetworkParameterInvalidKey",
NetworkParameterInvalidValue = "NetworkParameterInvalidValue",
NetworkParameterValidationFailed = "NetworkParameterValidationFailed",
NoProduct = "NoProduct",
NoRiskParameters = "NoRiskParameters",
NoTradingMode = "NoTradingMode",
NodeValidationFailed = "NodeValidationFailed",
OpeningAuctionDurationTooLarge = "OpeningAuctionDurationTooLarge",
OpeningAuctionDurationTooSmall = "OpeningAuctionDurationTooSmall",
ParticipationThresholdNotReached = "ParticipationThresholdNotReached",
ProductMaturityIsPassed = "ProductMaturityIsPassed",
UnsupportedProduct = "UnsupportedProduct",
UnsupportedTradingMode = "UnsupportedTradingMode",
}
/**
* Various states a proposal can transition through:
* Open ->
* - Passed -> Enacted.
* - Rejected.
* Proposal can enter Failed state from any other state.
*/
export enum ProposalState {
Declined = "Declined",
Enacted = "Enacted",
Failed = "Failed",
Open = "Open",
Passed = "Passed",
Rejected = "Rejected",
WaitingForNodeVote = "WaitingForNodeVote",
}
export enum VoteValue {
No = "No",
Yes = "Yes",
}
//==============================================================
// END Enums and Input Objects
//==============================================================

13
libs/graphql/src/index.ts Normal file
View File

@ -0,0 +1,13 @@
export * from './__generated__/AssetsQuery';
export * from './__generated__/globalTypes';
export * from './__generated__/Guess';
export * from './__generated__/Market';
export * from './__generated__/Markets';
export * from './__generated__/MarketsQuery';
export * from './__generated__/MarketDataSub';
export * from './__generated__/MarketDataFields';
export * from './__generated__/NetworkParametersQuery';
export * from './__generated__/NodesQuery';
export * from './__generated__/OrderEvent';
export * from './__generated__/PartyAssetsQuery';
export * from './__generated__/ProposalsQuery';

View File

@ -0,0 +1,25 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@ -0,0 +1,22 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": [
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

View File

@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.test.ts",
"**/*.spec.ts",
"**/*.test.tsx",
"**/*.spec.tsx",
"**/*.test.js",
"**/*.spec.js",
"**/*.test.jsx",
"**/*.spec.jsx",
"**/*.d.ts"
]
}

12
libs/market-list/.babelrc Normal file
View File

@ -0,0 +1,12 @@
{
"presets": [
[
"@nrwl/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}

View File

@ -0,0 +1,18 @@
{
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

View File

@ -0,0 +1,7 @@
# market-list
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test market-list` to execute the unit tests via [Jest](https://jestjs.io).

View File

@ -0,0 +1,9 @@
module.exports = {
displayName: 'market-list',
preset: '../../jest.preset.js',
transform: {
'^.+\\.[tj]sx?$': 'babel-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/market-list',
};

View File

@ -0,0 +1,4 @@
{
"name": "@vegaprotocol/market-list",
"version": "0.0.1"
}

View File

@ -0,0 +1,43 @@
{
"root": "libs/market-list",
"sourceRoot": "libs/market-list/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nrwl/web:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/market-list",
"tsConfig": "libs/market-list/tsconfig.lib.json",
"project": "libs/market-list/package.json",
"entryFile": "libs/market-list/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/market-list/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/market-list/**/*.{ts,tsx,js,jsx}"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/market-list"],
"options": {
"jestConfig": "libs/market-list/jest.config.js",
"passWithNoTests": true
}
}
}
}

View File

@ -0,0 +1 @@
export * from './lib/market-list-table';

View File

@ -0,0 +1,14 @@
import { render } from '@testing-library/react';
import { MockedProvider } from '@apollo/react-testing';
import MarketListTable from './market-list-table';
describe('MarketListTable', () => {
it('should render successfully', () => {
const { baseElement } = render(
<MockedProvider>
<MarketListTable width={100} height={100} />
</MockedProvider>
);
expect(baseElement).toBeTruthy();
});
});

View File

@ -0,0 +1,88 @@
import type { GridApi, ValueFormatterParams } from 'ag-grid-community';
import {
PriceCell,
formatNumber,
useApplyGridTransaction,
} from '@vegaprotocol/react-helpers';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import { Markets_markets } from '@vegaprotocol/graphql';
import { AgGridColumn } from 'ag-grid-react';
import { useRef, useState } from 'react';
interface MarketListTableProps {
markets: Markets_markets[];
onRowClicked: (marketId: string) => void;
}
export const MarketListTable = ({
markets,
onRowClicked,
}: MarketListTableProps) => {
const [initialMarkets] = useState(markets);
const gridApi = useRef<GridApi | null>(null);
useApplyGridTransaction(markets, gridApi.current);
return (
<AgGrid
style={{ width: '100%', height: '100%' }}
overlayNoRowsTemplate="No markets"
rowData={initialMarkets}
getRowNodeId={(data) => data.id}
defaultColDef={{
flex: 1,
resizable: true,
}}
onGridReady={(params) => {
gridApi.current = params.api;
}}
onRowClicked={({ data }) => onRowClicked(data.id)}
components={{ PriceCell }}
>
<AgGridColumn
headerName="Market"
field="tradableInstrument.instrument.code"
/>
<AgGridColumn
headerName="Settlement asset"
field="tradableInstrument.instrument.product.settlementAsset.symbol"
/>
<AgGridColumn
headerName="State"
field="data"
valueFormatter={({ value }: ValueFormatterParams) =>
`${value.market.state} (${value.market.tradingMode})`
}
/>
<AgGridColumn
headerName="Best bid"
field="data.bestBidPrice"
type="rightAligned"
cellRenderer="PriceCell"
valueFormatter={({ value, data }: ValueFormatterParams) =>
formatNumber(value, data.decimalPlaces)
}
/>
<AgGridColumn
headerName="Best offer"
field="data.bestOfferPrice"
type="rightAligned"
valueFormatter={({ value, data }: ValueFormatterParams) =>
formatNumber(value, data.decimalPlaces)
}
cellRenderer="PriceCell"
/>
<AgGridColumn
headerName="Mark price"
field="data.markPrice"
type="rightAligned"
cellRenderer="PriceCell"
valueFormatter={({ value, data }: ValueFormatterParams) =>
formatNumber(value, data.decimalPlaces)
}
/>
<AgGridColumn headerName="Description" field="name" />
</AgGrid>
);
};
export default MarketListTable;

View File

@ -0,0 +1,29 @@
import * as React from 'react';
/*
import { useMarketOverview } from '../../../../hooks/use-market-overview'
import { colorByMarketMovement } from '../../../../lib/vega-colours'
import { Sparkline } from '../../components/sparkline'
import { VEGA_TABLE_CLASSES } from '../../components/vega-table'
*/
export interface SummaryCellProps {
value: string; // marketId
}
export const SummaryCellView = ({ value }: SummaryCellProps) => {
// const { sparkline, change, bullish } = useMarketOverview(value)
// const color = colorByMarketMovement(bullish)
return (
<>
{/* <Sparkline data={sparkline} style={{ marginRight: 4 }} />*/}
<span>{'change'}</span>
</>
);
};
SummaryCellView.displayName = 'SummaryCellView';
export const SummaryCell = React.memo(SummaryCellView);
SummaryCell.displayName = 'SummaryCell';

View File

@ -0,0 +1,25 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@ -0,0 +1,22 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": [
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

View File

@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.test.ts",
"**/*.spec.ts",
"**/*.test.tsx",
"**/*.spec.tsx",
"**/*.test.js",
"**/*.spec.js",
"**/*.test.jsx",
"**/*.spec.jsx",
"**/*.d.ts"
]
}

View File

@ -0,0 +1,33 @@
import { GridApi } from 'ag-grid-community';
import { useEffect } from 'react';
export const useApplyGridTransaction = <T extends { id: string }>(
data: T[],
gridApi: GridApi | null
) => {
useEffect(() => {
if (!gridApi) return;
const update: T[] = [];
const add: T[] = [];
// split into updates and adds
data.forEach((d) => {
if (!gridApi) return;
const rowNode = gridApi.getRowNode(d.id);
if (rowNode) {
update.push(d);
} else {
add.push(d);
}
});
gridApi.applyTransaction({
update,
add,
addIndex: 0,
});
}, [data, gridApi]);
};

View File

@ -1,3 +1,8 @@
export * from './lib/context'; export * from './lib/context';
export * from './lib/datetime';
export * from './lib/decimals';
export * from './lib/format';
export * from './lib/grid-cells';
export * from './lib/storage'; export * from './lib/storage';
export * from './lib/trading';
export * from './hooks/use-apply-grid-transaction';

View File

@ -0,0 +1,13 @@
/** Returns date in a format suitable for input[type=date] elements */
export const formatForInput = (date: Date) => {
const padZero = (num: number) => num.toString().padStart(2, '0');
const year = date.getFullYear();
const month = padZero(date.getMonth() + 1);
const day = padZero(date.getDate());
const hours = padZero(date.getHours());
const minutes = padZero(date.getMinutes());
const secs = padZero(date.getSeconds());
return `${year}-${month}-${day}T${hours}:${minutes}:${secs}`;
};

View File

@ -0,0 +1 @@
export * from './datetime';

View File

@ -0,0 +1,12 @@
import { BigNumber } from 'bignumber.js';
export function addDecimal(value: string, decimals: number): string {
if (!decimals) return value;
return new BigNumber(value || 0)
.dividedBy(Math.pow(10, decimals))
.toFixed(decimals);
}
export function removeDecimal(value: string, decimals: number): string {
if (!decimals) return value;
return new BigNumber(value || 0).times(Math.pow(10, decimals)).toFixed(0);
}

View File

@ -0,0 +1,54 @@
import once from 'lodash.once';
import memoize from 'lodash.memoize';
import { addDecimal } from '../decimals';
const getUserLocale = () => 'default';
export const splitAt = (index: number) => (x: string) =>
[x.slice(0, index), x.slice(index)];
export const getTimeFormat = once(
() =>
new Intl.DateTimeFormat(getUserLocale(), {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
})
);
export const getDateFormat = once(
() =>
new Intl.DateTimeFormat(getUserLocale(), {
year: 'numeric',
month: 'numeric',
day: 'numeric',
})
);
export const getDateTimeFormat = once(
() =>
new Intl.DateTimeFormat(getUserLocale(), {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
})
);
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
export const getNumberFormat = memoize(
(minimumFractionDigits: number) =>
new Intl.NumberFormat(getUserLocale(), { minimumFractionDigits })
);
export const getRelativeTimeFormat = once(
() => new Intl.RelativeTimeFormat(getUserLocale())
);
export const formatNumber = (rawValue: string, decimalPlaces: number) => {
const x = addDecimal(rawValue, decimalPlaces);
return getNumberFormat(decimalPlaces).format(Number(x));
};

Some files were not shown because too many files have changed in this diff Show More