chore(trading): update order subs to not use busevents (#2849)

This commit is contained in:
Matthew Russell 2023-02-03 16:12:20 -08:00 committed by GitHub
parent 22abc8160c
commit 9ece19869d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 346 additions and 826 deletions

View File

@ -1 +0,0 @@
export { VegaTransaction } from './vega-transaction';

View File

@ -1,57 +0,0 @@
import { WithdrawalFeedback } from '@vegaprotocol/withdraws';
import { OrderFeedback } from '@vegaprotocol/orders';
import {
VegaDialog,
VegaTxStatus,
isWithdrawTransaction,
isOrderCancellationTransaction,
isOrderSubmissionTransaction,
isOrderAmendmentTransaction,
} from '@vegaprotocol/wallet';
import type { VegaStoredTxState } from '@vegaprotocol/wallet';
import { useEthWithdrawApprovalsStore } from '@vegaprotocol/web3';
export const VegaTransaction = ({
transaction,
}: {
transaction: VegaStoredTxState;
}) => {
const createEthWithdrawalApproval = useEthWithdrawApprovalsStore(
(state) => state.create
);
if (isWithdrawTransaction(transaction.body)) {
if (
transaction.status === VegaTxStatus.Complete &&
transaction.withdrawal
) {
return (
<WithdrawalFeedback
transaction={transaction}
withdrawal={transaction.withdrawal}
availableTimestamp={null}
submitWithdraw={() => {
if (!transaction?.withdrawal) {
return;
}
createEthWithdrawalApproval(
transaction.withdrawal,
transaction.withdrawalApproval
);
}}
/>
);
}
} else if (
(isOrderCancellationTransaction(transaction.body) ||
isOrderSubmissionTransaction(transaction.body) ||
isOrderAmendmentTransaction(transaction.body)) &&
transaction.status === VegaTxStatus.Complete &&
transaction.order
) {
return (
<OrderFeedback transaction={transaction} order={transaction.order} />
);
}
return <VegaDialog transaction={transaction} />;
};

View File

@ -134,23 +134,7 @@ const submitOrder: VegaStoredTxState = {
type: OrderType.TYPE_MARKET,
price: '1234',
createdAt: new Date(),
market: {
id: 'market-1',
decimalPlaces: 2,
positionDecimalPlaces: 2,
tradableInstrument: {
instrument: {
code: 'M1',
name: 'M1',
product: {
settlementAsset: {
decimals: 2,
symbol: '$A',
},
},
},
},
},
marketId: 'market-1',
status: OrderStatus.STATUS_ACTIVE,
},
};
@ -181,23 +165,7 @@ const editOrder: VegaStoredTxState = {
type: OrderType.TYPE_MARKET,
price: '1234',
createdAt: new Date(),
market: {
id: 'market-1',
decimalPlaces: 2,
positionDecimalPlaces: 2,
tradableInstrument: {
instrument: {
code: 'M1',
name: 'M1',
product: {
settlementAsset: {
decimals: 2,
symbol: '$A',
},
},
},
},
},
marketId: 'market-1',
status: OrderStatus.STATUS_ACTIVE,
},
};

View File

@ -4,7 +4,7 @@ import compact from 'lodash/compact';
import type {
BatchMarketInstructionSubmissionBody,
OrderAmendment,
OrderBusEventFieldsFragment,
OrderTxUpdateFieldsFragment,
OrderCancellationBody,
OrderSubmission,
VegaStoredTxState,
@ -130,12 +130,10 @@ const SubmitOrderDetails = ({
order,
}: {
data: OrderSubmission;
order?: OrderBusEventFieldsFragment;
order?: OrderTxUpdateFieldsFragment;
}) => {
const { data: markets } = useMarketList();
const market = order
? order.market
: markets?.find((m) => m.id === data.marketId);
const market = markets?.find((m) => m.id === order?.marketId);
if (!market) return null;
const price = order ? order.price : data.price;
@ -178,7 +176,7 @@ const EditOrderDetails = ({
order,
}: {
data: OrderAmendment;
order?: OrderBusEventFieldsFragment;
order?: OrderTxUpdateFieldsFragment;
}) => {
const { data: orderById } = useOrderByIdQuery({
variables: { orderId: data.orderId },
@ -242,7 +240,7 @@ const CancelOrderDetails = ({
order,
}: {
orderId: string;
order?: OrderBusEventFieldsFragment;
order?: OrderTxUpdateFieldsFragment;
}) => {
const { data: orderById } = useOrderByIdQuery({
variables: { orderId },

View File

@ -1,5 +1,4 @@
export * from './order-data-provider';
export * from './order-feedback';
export * from './order-list';
export * from './order-list-manager';
export * from './order-list-container';

View File

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

View File

@ -1,83 +0,0 @@
import { render, screen } from '@testing-library/react';
import * as Schema from '@vegaprotocol/types';
import { VegaTxStatus } from '@vegaprotocol/wallet';
import type { OrderEventFieldsFragment } from '../../order-hooks';
import { generateOrder } from '../mocks/generate-orders';
import type { OrderFeedbackProps } from './order-feedback';
import { OrderFeedback } from './order-feedback';
jest.mock('@vegaprotocol/environment', () => ({
useEnvironment: () => ({
VEGA_EXPLORER_URL: 'https://test.explorer.vega.network',
}),
}));
describe('OrderFeedback', () => {
let props: OrderFeedbackProps;
beforeEach(() => {
props = {
transaction: {
dialogOpen: false,
status: VegaTxStatus.Complete,
error: null,
txHash: 'tx-hash',
signature: null,
},
order: null,
};
});
it('renders null if no order provided', () => {
const { container } = render(<OrderFeedback {...props} />);
expect(container).toBeEmptyDOMElement();
});
it('renders error reason', () => {
const orderFields = {
status: Schema.OrderStatus.STATUS_REJECTED,
rejectionReason: Schema.OrderRejectionReason.ORDER_ERROR_AMEND_FAILURE,
};
const order = generateOrder(orderFields) as OrderEventFieldsFragment;
render(<OrderFeedback {...props} order={order} />);
expect(screen.getByTestId('error-reason')).toHaveTextContent(
`${Schema.OrderRejectionReasonMapping[orderFields.rejectionReason]}`
);
});
it('should render order details when order is placed successfully', () => {
const order = generateOrder({
type: Schema.OrderType.TYPE_LIMIT,
price: '100',
size: '200',
side: Schema.Side.SIDE_BUY,
market: {
decimalPlaces: 2,
positionDecimalPlaces: 0,
},
}) as OrderEventFieldsFragment;
render(<OrderFeedback {...props} order={order} />);
expect(screen.getByTestId('order-confirmed')).toBeInTheDocument();
expect(screen.getByTestId('tx-block-explorer')).toHaveTextContent(
// eslint-disable-next-line
props.transaction.txHash!
);
expect(screen.getByTestId('tx-block-explorer')).toHaveTextContent(
// eslint-disable-next-line
props.transaction.txHash!
);
expect(screen.getByText('Market').nextElementSibling).toHaveTextContent(
// eslint-disable-next-line
order.market!.tradableInstrument.instrument.name
);
expect(screen.getByText('Status').nextElementSibling).toHaveTextContent(
Schema.OrderStatusMapping[order.status]
);
expect(screen.getByText('Price').nextElementSibling).toHaveTextContent(
'1.00'
);
expect(screen.getByText('Size').nextElementSibling).toHaveTextContent(
`+200`
);
});
});

View File

@ -1,94 +0,0 @@
import { useEnvironment } from '@vegaprotocol/environment';
import type { OrderEventFieldsFragment } from '../../order-hooks/__generated__/OrderEvent';
import { addDecimalsFormatNumber, Size, t } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types';
import type { VegaTxState } from '@vegaprotocol/wallet';
import { Link } from '@vegaprotocol/ui-toolkit';
export interface OrderFeedbackProps {
transaction: VegaTxState;
order: OrderEventFieldsFragment | null;
}
export const OrderFeedback = ({ transaction, order }: OrderFeedbackProps) => {
const { VEGA_EXPLORER_URL } = useEnvironment();
const labelClass = 'font-bold text-black dark:text-white capitalize';
if (!order) return null;
const orderRejectionReason = getRejectionReason(order);
return (
<div data-testid="order-confirmed" className="w-full">
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-8">
{order.market && (
<div>
<p className={labelClass}>{t(`Market`)}</p>
<p>{t(`${order.market.tradableInstrument.instrument.name}`)}</p>
</div>
)}
<div>
<p className={labelClass}>{t(`Status`)}</p>
<p>{t(`${Schema.OrderStatusMapping[order.status]}`)}</p>
</div>
{order.type === Schema.OrderType.TYPE_LIMIT && order.market && (
<div>
<p className={labelClass}>{t(`Price`)}</p>
<p>
{addDecimalsFormatNumber(order.price, order.market.decimalPlaces)}
</p>
</div>
)}
<div>
<p className={labelClass}>{t(`Size`)}</p>
<p>
<Size
value={order.size}
side={order.side}
positionDecimalPlaces={order.market.positionDecimalPlaces}
/>
</p>
</div>
</div>
<div className="grid gap-8 mb-8">
{transaction.txHash && (
<div>
<p className={labelClass}>{t('Transaction')}</p>
<Link
style={{ wordBreak: 'break-word' }}
data-testid="tx-block-explorer"
href={`${VEGA_EXPLORER_URL}/txs/0x${transaction.txHash}`}
target="_blank"
rel="noreferrer"
>
{transaction.txHash}
</Link>
</div>
)}
{orderRejectionReason && (
<div>
<p className={labelClass}>{t(`Reason`)}</p>
<p data-testid="error-reason">{t(orderRejectionReason)}</p>
</div>
)}
</div>
</div>
);
};
export const getRejectionReason = (
order: OrderEventFieldsFragment
): string | null => {
switch (order.status) {
case Schema.OrderStatus.STATUS_STOPPED:
return t(
`Your ${
Schema.OrderTimeInForceMapping[order.timeInForce]
} order was not filled and it has been stopped`
);
default:
return order.rejectionReason
? t(Schema.OrderRejectionReasonMapping[order.rejectionReason])
: null;
}
};

View File

@ -23,7 +23,7 @@ import {
} from '@vegaprotocol/wallet';
import type { VegaTxState, TransactionResult } from '@vegaprotocol/wallet';
import { OrderEditDialog } from '../order-list/order-edit-dialog';
import type { OrderEventFieldsFragment } from '../../order-hooks';
import type { OrderSubFieldsFragment } from '../../order-hooks';
import * as Schema from '@vegaprotocol/types';
import type { Order } from '../order-data-provider';
@ -238,7 +238,7 @@ export const getCancelDialogIntent = ({
cancelledOrder,
transactionResult,
}: {
cancelledOrder: OrderEventFieldsFragment | null;
cancelledOrder: OrderSubFieldsFragment | null;
transactionResult?: TransactionResult;
}): Intent | undefined => {
if (cancelledOrder) {
@ -260,7 +260,7 @@ export const getCancelDialogTitle = ({
cancelledOrder,
transactionResult,
}: {
cancelledOrder: OrderEventFieldsFragment | null;
cancelledOrder: OrderSubFieldsFragment | null;
transactionResult?: TransactionResult;
}): string | undefined => {
if (cancelledOrder) {

View File

@ -1,33 +0,0 @@
fragment OrderEventFields on Order {
type
id
status
rejectionReason
createdAt
size
price
timeInForce
expiresAt
side
market {
id
decimalPlaces
positionDecimalPlaces
tradableInstrument {
instrument {
name
}
}
}
}
subscription OrderEvent($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Order]) {
type
event {
... on Order {
...OrderEventFields
}
}
}
}

View File

@ -0,0 +1,19 @@
fragment OrderSubFields on OrderUpdate {
type
id
status
rejectionReason
createdAt
size
price
timeInForce
expiresAt
side
marketId
}
subscription OrderSub($partyId: ID!) {
orders(partyId: $partyId) {
...OrderSubFields
}
}

View File

@ -1,73 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type OrderEventFieldsFragment = { __typename?: 'Order', type?: Types.OrderType | null, id: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, createdAt: any, size: string, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, side: Types.Side, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string } } } };
export type OrderEventSubscriptionVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type OrderEventSubscription = { __typename?: 'Subscription', busEvents?: Array<{ __typename?: 'BusEvent', type: Types.BusEventType, event: { __typename?: 'AccountEvent' } | { __typename?: 'Asset' } | { __typename?: 'AuctionEvent' } | { __typename?: 'Deposit' } | { __typename?: 'LiquidityProvision' } | { __typename?: 'LossSocialization' } | { __typename?: 'MarginLevels' } | { __typename?: 'Market' } | { __typename?: 'MarketData' } | { __typename?: 'MarketEvent' } | { __typename?: 'MarketTick' } | { __typename?: 'NodeSignature' } | { __typename?: 'OracleSpec' } | { __typename?: 'Order', type?: Types.OrderType | null, id: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, createdAt: any, size: string, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, side: Types.Side, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string } } } } | { __typename?: 'Party' } | { __typename?: 'PositionResolution' } | { __typename?: 'Proposal' } | { __typename?: 'RiskFactor' } | { __typename?: 'SettleDistressed' } | { __typename?: 'SettlePosition' } | { __typename?: 'TimeUpdate' } | { __typename?: 'Trade' } | { __typename?: 'TransactionResult' } | { __typename?: 'TransferResponses' } | { __typename?: 'Vote' } | { __typename?: 'Withdrawal' } }> | null };
export const OrderEventFieldsFragmentDoc = gql`
fragment OrderEventFields on Order {
type
id
status
rejectionReason
createdAt
size
price
timeInForce
expiresAt
side
market {
id
decimalPlaces
positionDecimalPlaces
tradableInstrument {
instrument {
name
}
}
}
}
`;
export const OrderEventDocument = gql`
subscription OrderEvent($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Order]) {
type
event {
... on Order {
...OrderEventFields
}
}
}
}
${OrderEventFieldsFragmentDoc}`;
/**
* __useOrderEventSubscription__
*
* To run a query within a React component, call `useOrderEventSubscription` and pass it any options that fit your needs.
* When your component renders, `useOrderEventSubscription` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useOrderEventSubscription({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useOrderEventSubscription(baseOptions: Apollo.SubscriptionHookOptions<OrderEventSubscription, OrderEventSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<OrderEventSubscription, OrderEventSubscriptionVariables>(OrderEventDocument, options);
}
export type OrderEventSubscriptionHookResult = ReturnType<typeof useOrderEventSubscription>;
export type OrderEventSubscriptionResult = Apollo.SubscriptionResult<OrderEventSubscription>;

View File

@ -0,0 +1,59 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type OrderSubFieldsFragment = { __typename?: 'OrderUpdate', type?: Types.OrderType | null, id: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, createdAt: any, size: string, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, side: Types.Side, marketId: string };
export type OrderSubSubscriptionVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type OrderSubSubscription = { __typename?: 'Subscription', orders?: Array<{ __typename?: 'OrderUpdate', type?: Types.OrderType | null, id: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, createdAt: any, size: string, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, side: Types.Side, marketId: string }> | null };
export const OrderSubFieldsFragmentDoc = gql`
fragment OrderSubFields on OrderUpdate {
type
id
status
rejectionReason
createdAt
size
price
timeInForce
expiresAt
side
marketId
}
`;
export const OrderSubDocument = gql`
subscription OrderSub($partyId: ID!) {
orders(partyId: $partyId) {
...OrderSubFields
}
}
${OrderSubFieldsFragmentDoc}`;
/**
* __useOrderSubSubscription__
*
* To run a query within a React component, call `useOrderSubSubscription` and pass it any options that fit your needs.
* When your component renders, `useOrderSubSubscription` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useOrderSubSubscription({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useOrderSubSubscription(baseOptions: Apollo.SubscriptionHookOptions<OrderSubSubscription, OrderSubSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<OrderSubSubscription, OrderSubSubscriptionVariables>(OrderSubDocument, options);
}
export type OrderSubSubscriptionHookResult = ReturnType<typeof useOrderSubSubscription>;
export type OrderSubSubscriptionResult = Apollo.SubscriptionResult<OrderSubSubscription>;

View File

@ -1,7 +1,7 @@
export * from './__generated__/OrderEvent';
export * from './__generated__/OrdersSubscription';
export * from './use-has-active-order';
export * from './use-order-cancel';
export * from './use-order-submit';
export * from './use-order-edit';
export * from './use-order-event';
export * from './use-order-update';
export * from './use-persisted-order';

View File

@ -5,8 +5,8 @@ import type { ReactNode } from 'react';
import { VegaTxStatus, VegaWalletContext } from '@vegaprotocol/wallet';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { useOrderCancel } from './use-order-cancel';
import type { OrderEventSubscription } from './';
import { OrderEventDocument } from './';
import type { OrderSubSubscription } from './';
import { OrderSubDocument } from './';
import * as Schema from '@vegaprotocol/types';
const defaultWalletContext = {
@ -21,89 +21,57 @@ const defaultWalletContext = {
};
function setup(context?: Partial<VegaWalletContextShape>) {
const mocks: MockedResponse<OrderEventSubscription> = {
const mocks: MockedResponse<OrderSubSubscription> = {
request: {
query: OrderEventDocument,
query: OrderSubDocument,
variables: {
partyId: context?.pubKey || '',
},
},
result: {
data: {
busEvents: [
orders: [
{
type: Schema.BusEventType.Order,
event: {
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
market: {
id: 'market-id',
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
name: 'UNIDAI Monthly (30 Jun 2022)',
__typename: 'Instrument',
},
},
__typename: 'Market',
},
__typename: 'Order',
},
__typename: 'BusEvent',
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
marketId: 'market-id',
__typename: 'OrderUpdate',
},
],
},
},
};
const filterMocks: MockedResponse<OrderEventSubscription> = {
const filterMocks: MockedResponse<OrderSubSubscription> = {
request: {
query: OrderEventDocument,
query: OrderSubDocument,
variables: {
partyId: context?.pubKey || '',
},
},
result: {
data: {
busEvents: [
orders: [
{
type: Schema.BusEventType.Order,
event: {
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
market: {
id: 'market-id',
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
name: 'UNIDAI Monthly (30 Jun 2022)',
__typename: 'Instrument',
},
},
__typename: 'Market',
},
__typename: 'Order',
},
__typename: 'BusEvent',
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
marketId: 'market-id',
__typename: 'OrderUpdate',
},
],
},

View File

@ -8,15 +8,15 @@ import type {
OrderCancellationBody,
TransactionResult,
} from '@vegaprotocol/wallet';
import type { OrderEventFieldsFragment } from './';
import type { OrderSubFieldsFragment } from './';
import * as Sentry from '@sentry/react';
import { useOrderEvent } from './use-order-event';
import { useOrderUpdate } from './use-order-update';
export const useOrderCancel = () => {
const { pubKey } = useVegaWallet();
const [cancelledOrder, setCancelledOrder] =
useState<OrderEventFieldsFragment | null>(null);
useState<OrderSubFieldsFragment | null>(null);
const [transactionResult, setTransactionResult] =
useState<TransactionResult>();
@ -28,7 +28,7 @@ export const useOrderCancel = () => {
Dialog,
} = useVegaTransaction();
const waitForOrderEvent = useOrderEvent(transaction);
const waitForOrderUpdate = useOrderUpdate(transaction);
const waitForTransactionResult = useTransactionResult();
const reset = useCallback(() => {
@ -49,7 +49,7 @@ export const useOrderCancel = () => {
orderCancellation,
});
if (orderCancellation.orderId) {
const cancelledOrder = await waitForOrderEvent(
const cancelledOrder = await waitForOrderUpdate(
orderCancellation.orderId,
pubKey
);
@ -69,7 +69,7 @@ export const useOrderCancel = () => {
return;
}
},
[pubKey, send, setComplete, waitForOrderEvent, waitForTransactionResult]
[pubKey, send, setComplete, waitForOrderUpdate, waitForTransactionResult]
);
return {

View File

@ -3,8 +3,8 @@ import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaTxStatus, VegaWalletContext } from '@vegaprotocol/wallet';
import type { ReactNode } from 'react';
import { useOrderEdit } from './use-order-edit';
import type { OrderEventSubscription } from './__generated__/OrderEvent';
import { OrderEventDocument } from './__generated__/OrderEvent';
import type { OrderSubSubscription } from './__generated__/OrdersSubscription';
import { OrderSubDocument } from './__generated__/OrdersSubscription';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import type { Order } from '../components';
@ -23,89 +23,57 @@ const defaultWalletContext = {
};
function setup(order: Order, context?: Partial<VegaWalletContextShape>) {
const mocks: MockedResponse<OrderEventSubscription> = {
const mocks: MockedResponse<OrderSubSubscription> = {
request: {
query: OrderEventDocument,
query: OrderSubDocument,
variables: {
partyId: context?.pubKey || '',
},
},
result: {
data: {
busEvents: [
orders: [
{
type: Schema.BusEventType.Order,
event: {
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
market: {
id: 'market-id',
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
name: 'UNIDAI Monthly (30 Jun 2022)',
__typename: 'Instrument',
},
},
__typename: 'Market',
},
__typename: 'Order',
},
__typename: 'BusEvent',
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
marketId: 'market-id',
__typename: 'OrderUpdate',
},
],
},
},
};
const filterMocks: MockedResponse<OrderEventSubscription> = {
const filterMocks: MockedResponse<OrderSubSubscription> = {
request: {
query: OrderEventDocument,
query: OrderSubDocument,
variables: {
partyId: context?.pubKey || '',
},
},
result: {
data: {
busEvents: [
orders: [
{
type: Schema.BusEventType.Order,
event: {
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
market: {
id: 'market-id',
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
name: 'UNIDAI Monthly (30 Jun 2022)',
__typename: 'Instrument',
},
},
__typename: 'Market',
},
__typename: 'Order',
},
__typename: 'BusEvent',
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
marketId: 'market-id',
__typename: 'OrderUpdate',
},
],
},

View File

@ -1,10 +1,10 @@
import { removeDecimal, toNanoSeconds } from '@vegaprotocol/react-helpers';
import { useState, useCallback } from 'react';
import { useVegaTransaction, useVegaWallet } from '@vegaprotocol/wallet';
import type { OrderEventFieldsFragment } from './';
import type { OrderSubFieldsFragment } from './';
import * as Sentry from '@sentry/react';
import type { Order } from '../components';
import { useOrderEvent } from './use-order-event';
import { useOrderUpdate } from './use-order-update';
import BigNumber from 'bignumber.js';
export interface EditOrderArgs {
@ -16,7 +16,7 @@ export const useOrderEdit = (order: Order | null) => {
const { pubKey } = useVegaWallet();
const [updatedOrder, setUpdatedOrder] =
useState<OrderEventFieldsFragment | null>(null);
useState<OrderSubFieldsFragment | null>(null);
const {
send,
@ -26,7 +26,7 @@ export const useOrderEdit = (order: Order | null) => {
Dialog,
} = useVegaTransaction();
const waitForOrderEvent = useOrderEvent(transaction);
const waitForOrderUpdate = useOrderUpdate(transaction);
const reset = useCallback(() => {
resetTransaction();
@ -61,7 +61,7 @@ export const useOrderEdit = (order: Order | null) => {
},
});
const updatedOrder = await waitForOrderEvent(order.id, pubKey);
const updatedOrder = await waitForOrderUpdate(order.id, pubKey);
setUpdatedOrder(updatedOrder);
setComplete();
} catch (e) {
@ -69,7 +69,7 @@ export const useOrderEdit = (order: Order | null) => {
return;
}
},
[pubKey, send, order, setComplete, waitForOrderEvent]
[pubKey, send, order, setComplete, waitForOrderUpdate]
);
return {

View File

@ -1,68 +0,0 @@
import { useApolloClient } from '@apollo/client';
import { useCallback, useEffect, useRef } from 'react';
import { OrderEventDocument } from './__generated__/OrderEvent';
import type {
OrderEventSubscription,
OrderEventSubscriptionVariables,
OrderEventFieldsFragment,
} from './__generated__/OrderEvent';
import type { Subscription } from 'zen-observable-ts';
import type { VegaTxState } from '@vegaprotocol/wallet';
import * as Schema from '@vegaprotocol/types';
type WaitFunc = (
orderId: string,
partyId: string
) => Promise<OrderEventFieldsFragment>;
export const useOrderEvent = (transaction: VegaTxState) => {
const client = useApolloClient();
const subRef = useRef<Subscription | null>(null);
const waitForOrderEvent = useCallback<WaitFunc>(
(id: string, partyId: string) => {
return new Promise((resolve) => {
subRef.current = client
.subscribe<OrderEventSubscription, OrderEventSubscriptionVariables>({
query: OrderEventDocument,
variables: { partyId },
})
.subscribe(({ data }) => {
if (!data?.busEvents?.length) {
return;
}
// No types available for the subscription result
const matchingOrderEvent = data.busEvents.find((e) => {
if (e.event.__typename !== Schema.BusEventType.Order) {
return false;
}
return e.event.id === id;
});
if (
matchingOrderEvent &&
matchingOrderEvent.event.__typename === Schema.BusEventType.Order
) {
resolve(matchingOrderEvent.event);
subRef.current?.unsubscribe();
}
});
});
},
[client]
);
useEffect(() => {
if (!transaction.dialogOpen) {
subRef.current?.unsubscribe();
}
return () => {
subRef.current?.unsubscribe();
};
}, [transaction.dialogOpen]);
return waitForOrderEvent;
};

View File

@ -5,8 +5,8 @@ import * as Schema from '@vegaprotocol/types';
import type { ReactNode } from 'react';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useOrderSubmit } from './use-order-submit';
import type { OrderEventSubscription } from './';
import { OrderEventDocument } from './';
import type { OrderSubSubscription } from './';
import { OrderSubDocument } from './';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
@ -48,89 +48,56 @@ const defaultWalletContext = {
};
function setup(context?: Partial<VegaWalletContextShape>) {
const mocks: MockedResponse<OrderEventSubscription> = {
const mocks: MockedResponse<OrderSubSubscription> = {
request: {
query: OrderEventDocument,
query: OrderSubDocument,
variables: {
partyId: context?.pubKey || '',
},
},
result: {
data: {
busEvents: [
orders: [
{
type: Schema.BusEventType.Order,
event: {
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
market: {
id: 'market-id',
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
name: 'UNIDAI Monthly (30 Jun 2022)',
__typename: 'Instrument',
},
},
__typename: 'Market',
},
__typename: 'Order',
},
__typename: 'BusEvent',
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
marketId: 'market-id',
},
],
},
},
};
const filterMocks: MockedResponse<OrderEventSubscription> = {
const filterMocks: MockedResponse<OrderSubSubscription> = {
request: {
query: OrderEventDocument,
query: OrderSubDocument,
variables: {
partyId: context?.pubKey || '',
},
},
result: {
data: {
busEvents: [
orders: [
{
type: Schema.BusEventType.Order,
event: {
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
market: {
id: 'market-id',
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
name: 'UNIDAI Monthly (30 Jun 2022)',
__typename: 'Instrument',
},
},
__typename: 'Market',
},
__typename: 'Order',
},
__typename: 'BusEvent',
type: Schema.OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: Schema.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Schema.Side.SIDE_BUY,
marketId: 'market-id',
__typename: 'OrderUpdate',
},
],
},

View File

@ -1,13 +1,13 @@
import { useCallback, useState } from 'react';
import type { ReactNode } from 'react';
import type { OrderEventFieldsFragment } from './__generated__/OrderEvent';
import type { OrderSubFieldsFragment } from './__generated__/OrdersSubscription';
import {
useVegaWallet,
useVegaTransaction,
determineId,
} from '@vegaprotocol/wallet';
import * as Sentry from '@sentry/react';
import { useOrderEvent } from './use-order-event';
import { useOrderUpdate } from './use-order-update';
import * as Schema from '@vegaprotocol/types';
import { Icon, Intent } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/react-helpers';
@ -96,10 +96,10 @@ export const useOrderSubmit = () => {
Dialog,
} = useVegaTransaction();
const waitForOrderEvent = useOrderEvent(transaction);
const waitForOrderUpdate = useOrderUpdate(transaction);
const [finalizedOrder, setFinalizedOrder] =
useState<OrderEventFieldsFragment | null>(null);
useState<OrderSubFieldsFragment | null>(null);
const reset = useCallback(() => {
resetTransaction();
@ -120,7 +120,7 @@ export const useOrderSubmit = () => {
if (res) {
const orderId = determineId(res.signature);
if (orderId) {
const order = await waitForOrderEvent(orderId, pubKey);
const order = await waitForOrderUpdate(orderId, pubKey);
setFinalizedOrder(order);
setComplete();
}
@ -129,7 +129,7 @@ export const useOrderSubmit = () => {
Sentry.captureException(e);
}
},
[pubKey, send, setComplete, waitForOrderEvent]
[pubKey, send, setComplete, waitForOrderUpdate]
);
return {

View File

@ -0,0 +1,60 @@
import { useApolloClient } from '@apollo/client';
import { useCallback, useEffect, useRef } from 'react';
import { OrderSubDocument } from './__generated__/OrdersSubscription';
import type {
OrderSubSubscription,
OrderSubSubscriptionVariables,
OrderSubFieldsFragment,
} from './__generated__/OrdersSubscription';
import type { Subscription } from 'zen-observable-ts';
import type { VegaTxState } from '@vegaprotocol/wallet';
type WaitFunc = (
orderId: string,
partyId: string
) => Promise<OrderSubFieldsFragment>;
export const useOrderUpdate = (transaction: VegaTxState) => {
const client = useApolloClient();
const subRef = useRef<Subscription | null>(null);
const waitForOrderUpdate = useCallback<WaitFunc>(
(id: string, partyId: string) => {
return new Promise((resolve) => {
subRef.current = client
.subscribe<OrderSubSubscription, OrderSubSubscriptionVariables>({
query: OrderSubDocument,
variables: { partyId },
})
.subscribe(({ data }) => {
if (!data?.orders?.length) {
return;
}
// No types available for the subscription result
const matchingOrder = data.orders.find((order) => {
return order.id === id;
});
if (matchingOrder) {
resolve(matchingOrder);
subRef.current?.unsubscribe();
}
});
});
},
[client]
);
useEffect(() => {
if (!transaction.dialogOpen) {
subRef.current?.unsubscribe();
}
return () => {
subRef.current?.unsubscribe();
};
}, [transaction.dialogOpen]);
return waitForOrderUpdate;
};

View File

@ -1,5 +1,6 @@
import { t } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types';
import type { OrderSubFieldsFragment } from './order-hooks';
// More detail in https://docs.vega.xyz/mainnet/graphql/enums/order-time-in-force
export const timeInForceLabel = (tif: string) => {
@ -20,3 +21,20 @@ export const timeInForceLabel = (tif: string) => {
return t(tif);
}
};
export const getRejectionReason = (
order: OrderSubFieldsFragment
): string | null => {
switch (order.status) {
case Schema.OrderStatus.STATUS_STOPPED:
return t(
`Your ${
Schema.OrderTimeInForceMapping[order.timeInForce]
} order was not filled and it has been stopped`
);
default:
return order.rejectionReason
? t(Schema.OrderRejectionReasonMapping[order.rejectionReason])
: null;
}
};

View File

@ -10,8 +10,8 @@ import { initialState } from '@vegaprotocol/wallet';
import type { TransactionEventSubscription } from '@vegaprotocol/wallet';
import { TransactionEventDocument } from '@vegaprotocol/wallet';
import { act } from 'react-dom/test-utils';
import type { OrderEventSubscription } from '@vegaprotocol/orders';
import { OrderEventDocument } from '@vegaprotocol/orders';
import type { OrderSubSubscription } from '@vegaprotocol/orders';
import { OrderSubDocument } from '@vegaprotocol/orders';
const pubKey = 'test-pubkey';
const defaultWalletContext = {
@ -52,45 +52,29 @@ function setup(context?: Partial<VegaWalletContextShape>) {
},
},
};
const mockOrderResult: MockedResponse<OrderEventSubscription> = {
const mockOrderResult: MockedResponse<OrderSubSubscription> = {
request: {
query: OrderEventDocument,
query: OrderSubDocument,
variables: {
partyId: context?.pubKey || '',
},
},
result: {
data: {
busEvents: [
orders: [
{
type: Types.BusEventType.Order,
event: {
type: Types.OrderType.TYPE_LIMIT,
id: '2fca514cebf9f465ae31ecb4c5721e3a6f5f260425ded887ca50ba15b81a5d50',
status: Types.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Types.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Types.Side.SIDE_BUY,
market: {
id: 'market-id',
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
name: 'UNIDAI Monthly (30 Jun 2022)',
__typename: 'Instrument',
},
},
__typename: 'Market',
},
__typename: 'Order',
},
__typename: 'BusEvent',
type: Types.OrderType.TYPE_LIMIT,
id: '2fca514cebf9f465ae31ecb4c5721e3a6f5f260425ded887ca50ba15b81a5d50',
status: Types.OrderStatus.STATUS_ACTIVE,
rejectionReason: null,
createdAt: '2022-07-05T14:25:47.815283706Z',
expiresAt: '2022-07-05T14:25:47.815283706Z',
size: '10',
price: '300000',
timeInForce: Types.OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Types.Side.SIDE_BUY,
marketId: 'market-id',
__typename: 'OrderUpdate',
},
],
},

View File

@ -5,8 +5,8 @@ import { useVegaWallet, useTransactionResult } from '@vegaprotocol/wallet';
import { useVegaTransaction } from '@vegaprotocol/wallet';
import * as Sentry from '@sentry/react';
import * as Schema from '@vegaprotocol/types';
import { useOrderEvent } from '@vegaprotocol/orders';
import type { OrderEventFieldsFragment } from '@vegaprotocol/orders';
import { useOrderUpdate } from '@vegaprotocol/orders';
import type { OrderSubFieldsFragment } from '@vegaprotocol/orders';
export interface ClosingOrder {
marketId: string;
@ -21,11 +21,11 @@ export const useClosePosition = () => {
const { send, transaction, setComplete, Dialog } = useVegaTransaction();
const [closingOrder, setClosingOrder] = useState<ClosingOrder>();
const [closingOrderResult, setClosingOrderResult] =
useState<OrderEventFieldsFragment>();
useState<OrderSubFieldsFragment>();
const [transactionResult, setTransactionResult] =
useState<TransactionResult>();
const waitForTransactionResult = useTransactionResult();
const waitForOrder = useOrderEvent(transaction);
const waitForOrder = useOrderUpdate(transaction);
const submit = useCallback(
async ({

View File

@ -3894,10 +3894,6 @@ export type Statistics = {
chainVersion: Scalars['String'];
/** RFC3339Nano current time (real) */
currentTime: Scalars['Timestamp'];
/** Total number of events on the last block */
eventCount: Scalars['String'];
/** The number of events per second on the last block */
eventsPerSecond: Scalars['String'];
/** RFC3339Nano genesis time of the chain */
genesisTime: Scalars['Timestamp'];
/** Number of orders per seconds */

View File

@ -53,7 +53,7 @@ subscription WithdrawalBusEvent($partyId: ID!) {
}
}
fragment OrderBusEventFields on Order {
fragment OrderTxUpdateFields on OrderUpdate {
type
id
status
@ -64,35 +64,12 @@ fragment OrderBusEventFields on Order {
timeInForce
expiresAt
side
market {
id
decimalPlaces
positionDecimalPlaces
tradableInstrument {
instrument {
name
code
product {
... on Future {
settlementAsset {
symbol
decimals
}
}
}
}
}
}
marketId
}
subscription OrderBusEvents($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Order]) {
type
event {
... on Order {
...OrderBusEventFields
}
}
subscription OrderTxUpdate($partyId: ID!) {
orders(partyId: $partyId) {
...OrderTxUpdateFields
}
}

View File

@ -21,14 +21,14 @@ export type WithdrawalBusEventSubscriptionVariables = Types.Exact<{
export type WithdrawalBusEventSubscription = { __typename?: 'Subscription', busEvents?: Array<{ __typename?: 'BusEvent', event: { __typename?: 'AccountEvent' } | { __typename?: 'Asset' } | { __typename?: 'AuctionEvent' } | { __typename?: 'Deposit' } | { __typename?: 'LiquidityProvision' } | { __typename?: 'LossSocialization' } | { __typename?: 'MarginLevels' } | { __typename?: 'Market' } | { __typename?: 'MarketData' } | { __typename?: 'MarketEvent' } | { __typename?: 'MarketTick' } | { __typename?: 'NodeSignature' } | { __typename?: 'OracleSpec' } | { __typename?: 'Order' } | { __typename?: 'Party' } | { __typename?: 'PositionResolution' } | { __typename?: 'Proposal' } | { __typename?: 'RiskFactor' } | { __typename?: 'SettleDistressed' } | { __typename?: 'SettlePosition' } | { __typename?: 'TimeUpdate' } | { __typename?: 'Trade' } | { __typename?: 'TransactionResult' } | { __typename?: 'TransferResponses' } | { __typename?: 'Vote' } | { __typename?: 'Withdrawal', id: string, status: Types.WithdrawalStatus, amount: string, createdTimestamp: any, withdrawnTimestamp?: any | null, txHash?: string | null, pendingOnForeignChain: boolean, asset: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, status: Types.AssetStatus, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } }, details?: { __typename?: 'Erc20WithdrawalDetails', receiverAddress: string } | null } }> | null };
export type OrderBusEventFieldsFragment = { __typename?: 'Order', type?: Types.OrderType | null, id: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, createdAt: any, size: string, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, side: Types.Side, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', symbol: string, decimals: number } } } } } };
export type OrderTxUpdateFieldsFragment = { __typename?: 'OrderUpdate', type?: Types.OrderType | null, id: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, createdAt: any, size: string, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, side: Types.Side, marketId: string };
export type OrderBusEventsSubscriptionVariables = Types.Exact<{
export type OrderTxUpdateSubscriptionVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type OrderBusEventsSubscription = { __typename?: 'Subscription', busEvents?: Array<{ __typename?: 'BusEvent', type: Types.BusEventType, event: { __typename?: 'AccountEvent' } | { __typename?: 'Asset' } | { __typename?: 'AuctionEvent' } | { __typename?: 'Deposit' } | { __typename?: 'LiquidityProvision' } | { __typename?: 'LossSocialization' } | { __typename?: 'MarginLevels' } | { __typename?: 'Market' } | { __typename?: 'MarketData' } | { __typename?: 'MarketEvent' } | { __typename?: 'MarketTick' } | { __typename?: 'NodeSignature' } | { __typename?: 'OracleSpec' } | { __typename?: 'Order', type?: Types.OrderType | null, id: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, createdAt: any, size: string, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, side: Types.Side, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', symbol: string, decimals: number } } } } } } | { __typename?: 'Party' } | { __typename?: 'PositionResolution' } | { __typename?: 'Proposal' } | { __typename?: 'RiskFactor' } | { __typename?: 'SettleDistressed' } | { __typename?: 'SettlePosition' } | { __typename?: 'TimeUpdate' } | { __typename?: 'Trade' } | { __typename?: 'TransactionResult' } | { __typename?: 'TransferResponses' } | { __typename?: 'Vote' } | { __typename?: 'Withdrawal' } }> | null };
export type OrderTxUpdateSubscription = { __typename?: 'Subscription', orders?: Array<{ __typename?: 'OrderUpdate', type?: Types.OrderType | null, id: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, createdAt: any, size: string, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, side: Types.Side, marketId: string }> | null };
export type DepositBusEventFieldsFragment = { __typename?: 'Deposit', id: string, status: Types.DepositStatus, amount: string, createdTimestamp: any, creditedTimestamp?: any | null, txHash?: string | null, asset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } };
@ -75,8 +75,8 @@ export const WithdrawalBusEventFieldsFragmentDoc = gql`
pendingOnForeignChain @client
}
`;
export const OrderBusEventFieldsFragmentDoc = gql`
fragment OrderBusEventFields on Order {
export const OrderTxUpdateFieldsFragmentDoc = gql`
fragment OrderTxUpdateFields on OrderUpdate {
type
id
status
@ -87,25 +87,7 @@ export const OrderBusEventFieldsFragmentDoc = gql`
timeInForce
expiresAt
side
market {
id
decimalPlaces
positionDecimalPlaces
tradableInstrument {
instrument {
name
code
product {
... on Future {
settlementAsset {
symbol
decimals
}
}
}
}
}
}
marketId
}
`;
export const DepositBusEventFieldsFragmentDoc = gql`
@ -192,41 +174,36 @@ export function useWithdrawalBusEventSubscription(baseOptions: Apollo.Subscripti
}
export type WithdrawalBusEventSubscriptionHookResult = ReturnType<typeof useWithdrawalBusEventSubscription>;
export type WithdrawalBusEventSubscriptionResult = Apollo.SubscriptionResult<WithdrawalBusEventSubscription>;
export const OrderBusEventsDocument = gql`
subscription OrderBusEvents($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Order]) {
type
event {
... on Order {
...OrderBusEventFields
}
}
export const OrderTxUpdateDocument = gql`
subscription OrderTxUpdate($partyId: ID!) {
orders(partyId: $partyId) {
...OrderTxUpdateFields
}
}
${OrderBusEventFieldsFragmentDoc}`;
${OrderTxUpdateFieldsFragmentDoc}`;
/**
* __useOrderBusEventsSubscription__
* __useOrderTxUpdateSubscription__
*
* To run a query within a React component, call `useOrderBusEventsSubscription` and pass it any options that fit your needs.
* When your component renders, `useOrderBusEventsSubscription` returns an object from Apollo Client that contains loading, error, and data properties
* To run a query within a React component, call `useOrderTxUpdateSubscription` and pass it any options that fit your needs.
* When your component renders, `useOrderTxUpdateSubscription` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useOrderBusEventsSubscription({
* const { data, loading, error } = useOrderTxUpdateSubscription({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useOrderBusEventsSubscription(baseOptions: Apollo.SubscriptionHookOptions<OrderBusEventsSubscription, OrderBusEventsSubscriptionVariables>) {
export function useOrderTxUpdateSubscription(baseOptions: Apollo.SubscriptionHookOptions<OrderTxUpdateSubscription, OrderTxUpdateSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<OrderBusEventsSubscription, OrderBusEventsSubscriptionVariables>(OrderBusEventsDocument, options);
return Apollo.useSubscription<OrderTxUpdateSubscription, OrderTxUpdateSubscriptionVariables>(OrderTxUpdateDocument, options);
}
export type OrderBusEventsSubscriptionHookResult = ReturnType<typeof useOrderBusEventsSubscription>;
export type OrderBusEventsSubscriptionResult = Apollo.SubscriptionResult<OrderBusEventsSubscription>;
export type OrderTxUpdateSubscriptionHookResult = ReturnType<typeof useOrderTxUpdateSubscription>;
export type OrderTxUpdateSubscriptionResult = Apollo.SubscriptionResult<OrderTxUpdateSubscription>;
export const DepositBusEventDocument = gql`
subscription DepositBusEvent($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Deposit]) {

View File

@ -15,7 +15,7 @@ import { VegaTxStatus } from './use-vega-transaction';
import type {
TransactionEventFieldsFragment,
WithdrawalBusEventFieldsFragment,
OrderBusEventFieldsFragment,
OrderTxUpdateFieldsFragment,
} from './__generated__/TransactionResult';
import type { WithdrawalApprovalQuery } from './__generated__/WithdrawalApproval';
@ -27,7 +27,7 @@ export interface VegaStoredTxState extends VegaTxState {
transactionResult?: TransactionEventFieldsFragment;
withdrawal?: WithdrawalBusEventFieldsFragment;
withdrawalApproval?: WithdrawalApprovalQuery['erc20WithdrawalApproval'];
order?: OrderBusEventFieldsFragment;
order?: OrderTxUpdateFieldsFragment;
}
export interface VegaTransactionStore {
transactions: (VegaStoredTxState | undefined)[];
@ -44,7 +44,7 @@ export interface VegaTransactionStore {
withdrawal: NonNullable<VegaStoredTxState['withdrawal']>,
withdrawalApproval: NonNullable<VegaStoredTxState['withdrawalApproval']>
) => void;
updateOrder: (order: OrderBusEventFieldsFragment) => void;
updateOrder: (order: OrderTxUpdateFieldsFragment) => void;
updateTransactionResult: (
transactionResult: TransactionEventFieldsFragment
) => void;
@ -124,7 +124,7 @@ export const useVegaTransactionStore = create<VegaTransactionStore>(
})
);
},
updateOrder: (order: OrderBusEventFieldsFragment) => {
updateOrder: (order) => {
set(
produce((state: VegaTransactionStore) => {
const transaction = state.transactions.find((transaction) => {

View File

@ -5,13 +5,13 @@ import type { ReactNode } from 'react';
import { useVegaTransactionUpdater } from './use-vega-transaction-updater';
import waitForNextTick from 'flush-promises';
import {
OrderBusEventsDocument,
OrderTxUpdateDocument,
TransactionEventDocument,
WithdrawalBusEventDocument,
} from './__generated__/TransactionResult';
import type {
OrderBusEventsSubscription,
OrderBusEventFieldsFragment,
OrderTxUpdateSubscription,
OrderTxUpdateFieldsFragment,
WithdrawalBusEventSubscription,
WithdrawalBusEventFieldsFragment,
TransactionEventSubscription,
@ -69,7 +69,7 @@ jest.mock('./use-vega-transaction-store', () => ({
) => selector(mockTransactionStoreState()),
}));
const orderBusEvent: OrderBusEventFieldsFragment = {
const orderUpdate: OrderTxUpdateFieldsFragment = {
type: OrderType.TYPE_LIMIT,
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
status: OrderStatus.STATUS_ACTIVE,
@ -80,43 +80,17 @@ const orderBusEvent: OrderBusEventFieldsFragment = {
price: '300000',
timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC,
side: Side.SIDE_BUY,
market: {
id: 'market-id',
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
name: 'UNIDAI Monthly (30 Jun 2022)',
code: 'UNIDAI',
product: {
__typename: 'Future',
settlementAsset: {
__typename: 'Asset',
decimals: 8,
symbol: 'AAA',
},
},
__typename: 'Instrument',
},
},
__typename: 'Market',
},
__typename: 'Order',
marketId: 'market-id',
__typename: 'OrderUpdate',
};
const mockedOrderBusEvent: MockedResponse<OrderBusEventsSubscription> = {
const mockedOrderUpdate: MockedResponse<OrderTxUpdateSubscription> = {
request: {
query: OrderBusEventsDocument,
query: OrderTxUpdateDocument,
variables: { partyId: pubKey },
},
result: {
data: {
busEvents: [
{
type: BusEventType.Order,
event: orderBusEvent,
},
],
orders: [orderUpdate],
},
},
};
@ -191,13 +165,13 @@ const mockedWithdrawalBusEvent: MockedResponse<WithdrawalBusEventSubscription> =
};
describe('useVegaTransactionManager', () => {
it('updates order on OrderBusEvents', async () => {
it('updates order on OrderTxUpdate', async () => {
mockTransactionStoreState.mockReturnValue(defaultState);
const { waitForNextUpdate } = render([mockedOrderBusEvent]);
const { waitForNextUpdate } = render([mockedOrderUpdate]);
await act(async () => {
waitForNextUpdate();
await waitForNextTick();
expect(updateOrder).toHaveBeenCalledWith(orderBusEvent);
expect(updateOrder).toHaveBeenCalledWith(orderUpdate);
});
});

View File

@ -1,7 +1,7 @@
import { useApolloClient } from '@apollo/client';
import { useVegaWallet } from './use-vega-wallet';
import {
useOrderBusEventsSubscription,
useOrderTxUpdateSubscription,
useWithdrawalBusEventSubscription,
useTransactionEventSubscription,
} from './__generated__/TransactionResult';
@ -21,14 +21,12 @@ export const useVegaTransactionUpdater = () => {
const variables = { partyId: pubKey || '' };
const skip = !pubKey;
useOrderBusEventsSubscription({
useOrderTxUpdateSubscription({
variables,
skip,
onData: ({ data: result }) =>
result.data?.busEvents?.forEach((event) => {
if (event.event.__typename === 'Order') {
updateOrder(event.event);
}
result.data?.orders?.forEach((order) => {
updateOrder(order);
}),
});