feat(trading): use custom toast content for stop order related transactions (#4476)
This commit is contained in:
parent
9cc8f5a377
commit
26d5a67604
@ -150,3 +150,9 @@ query StopOrders($partyId: ID!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query StopOrderById($stopOrderId: ID!) {
|
||||||
|
stopOrder(id: $stopOrderId) {
|
||||||
|
...StopOrderFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -32,7 +32,7 @@ export type OrdersUpdateSubscriptionVariables = Types.Exact<{
|
|||||||
|
|
||||||
export type OrdersUpdateSubscription = { __typename?: 'Subscription', orders?: Array<{ __typename?: 'OrderUpdate', id: string, marketId: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, liquidityProvisionId?: string | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, icebergOrder?: { __typename: 'IcebergOrder', peakSize: string, minimumVisibleSize: string, reservedRemaining: string } | null }> | null };
|
export type OrdersUpdateSubscription = { __typename?: 'Subscription', orders?: Array<{ __typename?: 'OrderUpdate', id: string, marketId: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, liquidityProvisionId?: string | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, icebergOrder?: { __typename: 'IcebergOrder', peakSize: string, minimumVisibleSize: string, reservedRemaining: string } | null }> | null };
|
||||||
|
|
||||||
export type OrderSubmissionFieldsFragment = { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null};
|
export type OrderSubmissionFieldsFragment = { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null };
|
||||||
|
|
||||||
export type StopOrderFieldsFragment = { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger?: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string } | null, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } };
|
export type StopOrderFieldsFragment = { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger?: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string } | null, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } };
|
||||||
|
|
||||||
@ -43,6 +43,13 @@ export type StopOrdersQueryVariables = Types.Exact<{
|
|||||||
|
|
||||||
export type StopOrdersQuery = { __typename?: 'Query', stopOrders?: { __typename?: 'StopOrderConnection', edges?: Array<{ __typename?: 'StopOrderEdge', node?: { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger?: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string } | null, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } } | null }> | null } | null };
|
export type StopOrdersQuery = { __typename?: 'Query', stopOrders?: { __typename?: 'StopOrderConnection', edges?: Array<{ __typename?: 'StopOrderEdge', node?: { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger?: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string } | null, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } } | null }> | null } | null };
|
||||||
|
|
||||||
|
export type StopOrderByIdQueryVariables = Types.Exact<{
|
||||||
|
stopOrderId: Types.Scalars['ID'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type StopOrderByIdQuery = { __typename?: 'Query', stopOrder?: { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger?: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string } | null, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } } | null };
|
||||||
|
|
||||||
export const OrderFieldsFragmentDoc = gql`
|
export const OrderFieldsFragmentDoc = gql`
|
||||||
fragment OrderFields on Order {
|
fragment OrderFields on Order {
|
||||||
id
|
id
|
||||||
@ -309,4 +316,39 @@ export function useStopOrdersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions
|
|||||||
}
|
}
|
||||||
export type StopOrdersQueryHookResult = ReturnType<typeof useStopOrdersQuery>;
|
export type StopOrdersQueryHookResult = ReturnType<typeof useStopOrdersQuery>;
|
||||||
export type StopOrdersLazyQueryHookResult = ReturnType<typeof useStopOrdersLazyQuery>;
|
export type StopOrdersLazyQueryHookResult = ReturnType<typeof useStopOrdersLazyQuery>;
|
||||||
export type StopOrdersQueryResult = Apollo.QueryResult<StopOrdersQuery, StopOrdersQueryVariables>;
|
export type StopOrdersQueryResult = Apollo.QueryResult<StopOrdersQuery, StopOrdersQueryVariables>;
|
||||||
|
export const StopOrderByIdDocument = gql`
|
||||||
|
query StopOrderById($stopOrderId: ID!) {
|
||||||
|
stopOrder(id: $stopOrderId) {
|
||||||
|
...StopOrderFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${StopOrderFieldsFragmentDoc}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useStopOrderByIdQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useStopOrderByIdQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useStopOrderByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useStopOrderByIdQuery({
|
||||||
|
* variables: {
|
||||||
|
* stopOrderId: // value for 'stopOrderId'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useStopOrderByIdQuery(baseOptions: Apollo.QueryHookOptions<StopOrderByIdQuery, StopOrderByIdQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useQuery<StopOrderByIdQuery, StopOrderByIdQueryVariables>(StopOrderByIdDocument, options);
|
||||||
|
}
|
||||||
|
export function useStopOrderByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<StopOrderByIdQuery, StopOrderByIdQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useLazyQuery<StopOrderByIdQuery, StopOrderByIdQueryVariables>(StopOrderByIdDocument, options);
|
||||||
|
}
|
||||||
|
export type StopOrderByIdQueryHookResult = ReturnType<typeof useStopOrderByIdQuery>;
|
||||||
|
export type StopOrderByIdLazyQueryHookResult = ReturnType<typeof useStopOrderByIdLazyQuery>;
|
||||||
|
export type StopOrderByIdQueryResult = Apollo.QueryResult<StopOrderByIdQuery, StopOrderByIdQueryVariables>;
|
@ -3,6 +3,7 @@ import {
|
|||||||
getDateTimeFormat,
|
getDateTimeFormat,
|
||||||
isNumeric,
|
isNumeric,
|
||||||
toBigNum,
|
toBigNum,
|
||||||
|
formatTrigger,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
@ -55,29 +56,8 @@ export const StopOrdersTable = memo<
|
|||||||
sortable: false,
|
sortable: false,
|
||||||
valueFormatter: ({
|
valueFormatter: ({
|
||||||
data,
|
data,
|
||||||
value,
|
}: VegaValueFormatterParams<StopOrder, 'trigger'>): string =>
|
||||||
}: VegaValueFormatterParams<StopOrder, 'trigger'>): string => {
|
data ? formatTrigger(data, data.market.decimalPlaces) : '',
|
||||||
if (data && value?.__typename === 'StopOrderPrice') {
|
|
||||||
return `${t('Mark')} ${
|
|
||||||
data?.triggerDirection ===
|
|
||||||
Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW
|
|
||||||
? '<'
|
|
||||||
: '>'
|
|
||||||
} ${addDecimalsFormatNumber(
|
|
||||||
value.price,
|
|
||||||
data.market.decimalPlaces
|
|
||||||
)}`;
|
|
||||||
}
|
|
||||||
if (data && value?.__typename === 'StopOrderTrailingPercentOffset') {
|
|
||||||
return `${t('Mark')} ${
|
|
||||||
data?.triggerDirection ===
|
|
||||||
Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW
|
|
||||||
? '+'
|
|
||||||
: '-'
|
|
||||||
}${(Number(value.trailingPercentOffset) * 100).toFixed(1)}%`;
|
|
||||||
}
|
|
||||||
return '-';
|
|
||||||
},
|
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -3,3 +3,4 @@ export * from './number';
|
|||||||
export * from './range';
|
export * from './range';
|
||||||
export * from './size';
|
export * from './size';
|
||||||
export * from './strings';
|
export * from './strings';
|
||||||
|
export * from './trigger';
|
||||||
|
27
libs/utils/src/lib/format/trigger.ts
Normal file
27
libs/utils/src/lib/format/trigger.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import * as Schema from '@vegaprotocol/types';
|
||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { addDecimalsFormatNumber } from './number';
|
||||||
|
|
||||||
|
export const formatTrigger = (
|
||||||
|
data: Pick<Schema.StopOrder, 'trigger' | 'triggerDirection'> | undefined,
|
||||||
|
marketDecimalPlaces: number,
|
||||||
|
defaultValue = '-'
|
||||||
|
) => {
|
||||||
|
if (data && data?.trigger?.__typename === 'StopOrderPrice') {
|
||||||
|
return `${t('Mark')} ${
|
||||||
|
data?.triggerDirection ===
|
||||||
|
Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW
|
||||||
|
? '<'
|
||||||
|
: '>'
|
||||||
|
} ${addDecimalsFormatNumber(data.trigger.price, marketDecimalPlaces)}`;
|
||||||
|
}
|
||||||
|
if (data && data?.trigger?.__typename === 'StopOrderTrailingPercentOffset') {
|
||||||
|
return `${t('Mark')} ${
|
||||||
|
data?.triggerDirection ===
|
||||||
|
Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW
|
||||||
|
? '+'
|
||||||
|
: '-'
|
||||||
|
}${(Number(data?.trigger.trailingPercentOffset) * 100).toFixed(1)}%`;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
};
|
@ -12,6 +12,7 @@ import {
|
|||||||
getVegaTransactionContentIntent,
|
getVegaTransactionContentIntent,
|
||||||
} from './use-vega-transaction-toasts';
|
} from './use-vega-transaction-toasts';
|
||||||
import { Intent } from '@vegaprotocol/ui-toolkit';
|
import { Intent } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import type { OrderByIdQuery, StopOrderByIdQuery } from '@vegaprotocol/orders';
|
||||||
|
|
||||||
jest.mock('@vegaprotocol/assets', () => {
|
jest.mock('@vegaprotocol/assets', () => {
|
||||||
const A1 = {
|
const A1 = {
|
||||||
@ -23,7 +24,7 @@ jest.mock('@vegaprotocol/assets', () => {
|
|||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
...jest.requireActual('@vegaprotocol/assets'),
|
...jest.requireActual('@vegaprotocol/assets'),
|
||||||
useAssetsDataProvider: jest.fn(() => ({ data: [A1] })),
|
useAssetsMapProvider: jest.fn(() => ({ data: { [A1.id]: A1 } })),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ jest.mock('@vegaprotocol/markets', () => {
|
|||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
...jest.requireActual('@vegaprotocol/markets'),
|
...jest.requireActual('@vegaprotocol/markets'),
|
||||||
useMarketList: jest.fn(() => ({ data: [M1] })),
|
useMarketsMapProvider: jest.fn(() => ({ data: { [M1.id]: M1 } })),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -59,20 +60,64 @@ jest.mock('@vegaprotocol/orders', () => {
|
|||||||
...jest.requireActual('@vegaprotocol/orders'),
|
...jest.requireActual('@vegaprotocol/orders'),
|
||||||
useOrderByIdQuery: jest.fn(({ variables: { orderId } }) => {
|
useOrderByIdQuery: jest.fn(({ variables: { orderId } }) => {
|
||||||
if (orderId === '0') {
|
if (orderId === '0') {
|
||||||
return {
|
const data: OrderByIdQuery = {
|
||||||
data: {
|
orderByID: {
|
||||||
orderByID: {
|
id: '0',
|
||||||
id: '0',
|
side: 'SIDE_BUY',
|
||||||
side: 'SIDE_BUY',
|
size: '10',
|
||||||
size: '10',
|
remaining: '10',
|
||||||
timeInForce: 'TIME_IN_FORCE_FOK',
|
timeInForce: 'TIME_IN_FORCE_FOK',
|
||||||
type: 'TYPE_MARKET',
|
type: 'TYPE_MARKET',
|
||||||
price: '1234',
|
price: '1234',
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
status: 'STATUS_ACTIVE',
|
status: 'STATUS_ACTIVE',
|
||||||
market: { id: 'market-1' },
|
market: { id: 'market-1' },
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
} as OrderByIdQuery;
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return { data: undefined };
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
useStopOrderByIdQuery: jest.fn(({ variables: { stopOrderId } }) => {
|
||||||
|
if (stopOrderId === '0') {
|
||||||
|
const data: StopOrderByIdQuery = {
|
||||||
|
stopOrder: {
|
||||||
|
id: '0',
|
||||||
|
ocoLinkId: null,
|
||||||
|
expiresAt: null,
|
||||||
|
expiryStrategy: null,
|
||||||
|
triggerDirection: 'TRIGGER_DIRECTION_RISES_ABOVE',
|
||||||
|
status: 'STATUS_CANCELLED',
|
||||||
|
createdAt: '2023-08-03T07:12:36.325927Z',
|
||||||
|
updatedAt: null,
|
||||||
|
partyId: 'party-id',
|
||||||
|
marketId: 'market-1',
|
||||||
|
trigger: {
|
||||||
|
price: '1234',
|
||||||
|
__typename: 'StopOrderPrice',
|
||||||
|
},
|
||||||
|
submission: {
|
||||||
|
marketId: 'market-1',
|
||||||
|
price: '1234',
|
||||||
|
size: '10',
|
||||||
|
side: 'SIDE_SELL',
|
||||||
|
timeInForce: 'TIME_IN_FORCE_FOK',
|
||||||
|
expiresAt: null,
|
||||||
|
type: 'TYPE_MARKET',
|
||||||
|
reference: '',
|
||||||
|
peggedOrder: null,
|
||||||
|
postOnly: false,
|
||||||
|
reduceOnly: true,
|
||||||
|
__typename: 'OrderSubmission',
|
||||||
|
},
|
||||||
|
__typename: 'StopOrder',
|
||||||
|
},
|
||||||
|
} as StopOrderByIdQuery;
|
||||||
|
return {
|
||||||
|
data,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return { data: undefined };
|
return { data: undefined };
|
||||||
@ -143,6 +188,31 @@ const submitOrder: VegaStoredTxState = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const submitStopOrder: VegaStoredTxState = {
|
||||||
|
id: 0,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
body: {
|
||||||
|
stopOrdersSubmission: {
|
||||||
|
risesAbove: {
|
||||||
|
price: '1234',
|
||||||
|
orderSubmission: {
|
||||||
|
marketId: 'market-1',
|
||||||
|
side: Side.SIDE_BUY,
|
||||||
|
size: '10',
|
||||||
|
timeInForce: OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||||
|
type: OrderType.TYPE_MARKET,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
status: VegaTxStatus.Default,
|
||||||
|
error: null,
|
||||||
|
txHash: null,
|
||||||
|
signature: null,
|
||||||
|
dialogOpen: false,
|
||||||
|
};
|
||||||
|
|
||||||
const editOrder: VegaStoredTxState = {
|
const editOrder: VegaStoredTxState = {
|
||||||
id: 0,
|
id: 0,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
@ -208,6 +278,23 @@ const cancelAll: VegaStoredTxState = {
|
|||||||
dialogOpen: false,
|
dialogOpen: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cancelStopOrder: VegaStoredTxState = {
|
||||||
|
id: 0,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
body: {
|
||||||
|
stopOrdersCancellation: {
|
||||||
|
marketId: 'market-1',
|
||||||
|
stopOrderId: '0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
status: VegaTxStatus.Default,
|
||||||
|
error: null,
|
||||||
|
txHash: null,
|
||||||
|
signature: null,
|
||||||
|
dialogOpen: false,
|
||||||
|
};
|
||||||
|
|
||||||
const closePosition: VegaStoredTxState = {
|
const closePosition: VegaStoredTxState = {
|
||||||
id: 0,
|
id: 0,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
@ -269,12 +356,20 @@ describe('VegaTransactionDetails', () => {
|
|||||||
it.each([
|
it.each([
|
||||||
{ tx: withdraw, details: 'Withdraw 12.34 $A' },
|
{ tx: withdraw, details: 'Withdraw 12.34 $A' },
|
||||||
{ tx: submitOrder, details: 'Submit order - activeM1+0.10 @ 12.34 $A' },
|
{ tx: submitOrder, details: 'Submit order - activeM1+0.10 @ 12.34 $A' },
|
||||||
|
{
|
||||||
|
tx: submitStopOrder,
|
||||||
|
details: 'Submit stop orderM1+0.10 @ ~ $AMark > 12.34',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
tx: editOrder,
|
tx: editOrder,
|
||||||
details: 'Edit order - activeM1+0.10 @ 12.34 $A+0.11 @ 10.00 $A',
|
details: 'Edit order - activeM1+0.10 @ 12.34 $A+0.11 @ 10.00 $A',
|
||||||
},
|
},
|
||||||
{ tx: cancelOrder, details: 'Cancel orderM1+0.10 @ 12.34 $A' },
|
{ tx: cancelOrder, details: 'Cancel orderM1+0.10 @ 12.34 $A' },
|
||||||
{ tx: cancelAll, details: 'Cancel all orders' },
|
{ tx: cancelAll, details: 'Cancel all orders' },
|
||||||
|
{
|
||||||
|
tx: cancelStopOrder,
|
||||||
|
details: 'Cancel stop orderM1-0.10 @ 12.34 $AMark > 12.34',
|
||||||
|
},
|
||||||
{ tx: closePosition, details: 'Close position for M1' },
|
{ tx: closePosition, details: 'Close position for M1' },
|
||||||
{ tx: batch, details: 'Batch market instruction' },
|
{ tx: batch, details: 'Batch market instruction' },
|
||||||
])('display details for transaction', ({ tx, details }) => {
|
])('display details for transaction', ({ tx, details }) => {
|
||||||
@ -291,12 +386,18 @@ describe('getVegaTransactionContentIntent', () => {
|
|||||||
expect(getVegaTransactionContentIntent(submitOrder).intent).toBe(
|
expect(getVegaTransactionContentIntent(submitOrder).intent).toBe(
|
||||||
Intent.Success
|
Intent.Success
|
||||||
);
|
);
|
||||||
|
expect(getVegaTransactionContentIntent(submitStopOrder).intent).toBe(
|
||||||
|
Intent.Primary
|
||||||
|
);
|
||||||
expect(getVegaTransactionContentIntent(editOrder).intent).toBe(
|
expect(getVegaTransactionContentIntent(editOrder).intent).toBe(
|
||||||
Intent.Primary
|
Intent.Primary
|
||||||
);
|
);
|
||||||
expect(getVegaTransactionContentIntent(cancelOrder).intent).toBe(
|
expect(getVegaTransactionContentIntent(cancelOrder).intent).toBe(
|
||||||
Intent.Primary
|
Intent.Primary
|
||||||
);
|
);
|
||||||
|
expect(getVegaTransactionContentIntent(cancelStopOrder).intent).toBe(
|
||||||
|
Intent.Primary
|
||||||
|
);
|
||||||
expect(getVegaTransactionContentIntent(cancelAll).intent).toBe(
|
expect(getVegaTransactionContentIntent(cancelAll).intent).toBe(
|
||||||
Intent.Primary
|
Intent.Primary
|
||||||
);
|
);
|
||||||
|
@ -5,10 +5,10 @@ import type {
|
|||||||
BatchMarketInstructionSubmissionBody,
|
BatchMarketInstructionSubmissionBody,
|
||||||
OrderAmendment,
|
OrderAmendment,
|
||||||
OrderTxUpdateFieldsFragment,
|
OrderTxUpdateFieldsFragment,
|
||||||
OrderCancellationBody,
|
|
||||||
OrderSubmission,
|
OrderSubmission,
|
||||||
VegaStoredTxState,
|
VegaStoredTxState,
|
||||||
WithdrawalBusEventFieldsFragment,
|
WithdrawalBusEventFieldsFragment,
|
||||||
|
StopOrdersSubmission,
|
||||||
} from '@vegaprotocol/wallet';
|
} from '@vegaprotocol/wallet';
|
||||||
import {
|
import {
|
||||||
isTransferTransaction,
|
isTransferTransaction,
|
||||||
@ -36,9 +36,10 @@ import {
|
|||||||
formatNumber,
|
formatNumber,
|
||||||
toBigNum,
|
toBigNum,
|
||||||
truncateByChars,
|
truncateByChars,
|
||||||
|
formatTrigger,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { useAssetsDataProvider } from '@vegaprotocol/assets';
|
import { useAssetsMapProvider } from '@vegaprotocol/assets';
|
||||||
import { useEthWithdrawApprovalsStore } from './use-ethereum-withdraw-approvals-store';
|
import { useEthWithdrawApprovalsStore } from './use-ethereum-withdraw-approvals-store';
|
||||||
import { DApp, EXPLORER_TX, useLinks } from '@vegaprotocol/environment';
|
import { DApp, EXPLORER_TX, useLinks } from '@vegaprotocol/environment';
|
||||||
import {
|
import {
|
||||||
@ -46,8 +47,9 @@ import {
|
|||||||
getOrderToastTitle,
|
getOrderToastTitle,
|
||||||
getRejectionReason,
|
getRejectionReason,
|
||||||
useOrderByIdQuery,
|
useOrderByIdQuery,
|
||||||
|
useStopOrderByIdQuery,
|
||||||
} from '@vegaprotocol/orders';
|
} from '@vegaprotocol/orders';
|
||||||
import { useMarketList } from '@vegaprotocol/markets';
|
import { useMarketsMapProvider } from '@vegaprotocol/markets';
|
||||||
import type { Side } from '@vegaprotocol/types';
|
import type { Side } from '@vegaprotocol/types';
|
||||||
import { OrderStatusMapping } from '@vegaprotocol/types';
|
import { OrderStatusMapping } from '@vegaprotocol/types';
|
||||||
import { Size } from '@vegaprotocol/datagrid';
|
import { Size } from '@vegaprotocol/datagrid';
|
||||||
@ -136,8 +138,8 @@ const SubmitOrderDetails = ({
|
|||||||
data: OrderSubmission;
|
data: OrderSubmission;
|
||||||
order?: OrderTxUpdateFieldsFragment;
|
order?: OrderTxUpdateFieldsFragment;
|
||||||
}) => {
|
}) => {
|
||||||
const { data: markets } = useMarketList();
|
const { data: markets } = useMarketsMapProvider();
|
||||||
const market = markets?.find((m) => m.id === order?.marketId);
|
const market = markets?.[order?.marketId || ''];
|
||||||
if (!market) return null;
|
if (!market) return null;
|
||||||
|
|
||||||
const price = order ? order.price : data.price;
|
const price = order ? order.price : data.price;
|
||||||
@ -172,6 +174,58 @@ const SubmitOrderDetails = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SubmitStopOrderDetails = ({ data }: { data: StopOrdersSubmission }) => {
|
||||||
|
const { data: markets } = useMarketsMapProvider();
|
||||||
|
const stopOrderSetup = data.risesAbove || data.fallsBelow;
|
||||||
|
if (!stopOrderSetup) return null;
|
||||||
|
const market = markets?.[stopOrderSetup?.orderSubmission.marketId];
|
||||||
|
if (!market || !stopOrderSetup) return null;
|
||||||
|
|
||||||
|
const { price, size, side } = stopOrderSetup.orderSubmission;
|
||||||
|
let trigger: Schema.StopOrderTrigger | null = null;
|
||||||
|
if (stopOrderSetup.price) {
|
||||||
|
trigger = { price: stopOrderSetup.price, __typename: 'StopOrderPrice' };
|
||||||
|
} else if (stopOrderSetup.trailingPercentOffset) {
|
||||||
|
trigger = {
|
||||||
|
trailingPercentOffset: stopOrderSetup.trailingPercentOffset,
|
||||||
|
__typename: 'StopOrderTrailingPercentOffset',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const triggerDirection = data.risesAbove
|
||||||
|
? Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_RISES_ABOVE
|
||||||
|
: Schema.StopOrderTriggerDirection.TRIGGER_DIRECTION_FALLS_BELOW;
|
||||||
|
return (
|
||||||
|
<Panel>
|
||||||
|
<h4>{t('Submit stop order')}</h4>
|
||||||
|
<p>{market?.tradableInstrument.instrument.code}</p>
|
||||||
|
<p>
|
||||||
|
<SizeAtPrice
|
||||||
|
meta={{
|
||||||
|
positionDecimalPlaces: market.positionDecimalPlaces,
|
||||||
|
decimalPlaces: market.decimalPlaces,
|
||||||
|
asset:
|
||||||
|
market.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
.symbol,
|
||||||
|
}}
|
||||||
|
side={side}
|
||||||
|
size={size}
|
||||||
|
price={price}
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
{trigger &&
|
||||||
|
formatTrigger(
|
||||||
|
{
|
||||||
|
triggerDirection,
|
||||||
|
trigger,
|
||||||
|
},
|
||||||
|
market.decimalPlaces,
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</Panel>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const EditOrderDetails = ({
|
const EditOrderDetails = ({
|
||||||
data,
|
data,
|
||||||
order,
|
order,
|
||||||
@ -183,13 +237,12 @@ const EditOrderDetails = ({
|
|||||||
variables: { orderId: data.orderId },
|
variables: { orderId: data.orderId },
|
||||||
fetchPolicy: 'no-cache',
|
fetchPolicy: 'no-cache',
|
||||||
});
|
});
|
||||||
const { data: markets } = useMarketList();
|
const { data: markets } = useMarketsMapProvider();
|
||||||
|
|
||||||
const originalOrder = order || orderById?.orderByID;
|
const originalOrder = order || orderById?.orderByID;
|
||||||
const marketId = order?.marketId || orderById?.orderByID.market.id;
|
const marketId = order?.marketId || orderById?.orderByID.market.id;
|
||||||
if (!originalOrder) return null;
|
const market = markets?.[marketId || ''];
|
||||||
const market = markets?.find((m) => m.id === marketId);
|
if (!originalOrder || !market) return null;
|
||||||
if (!market) return null;
|
|
||||||
|
|
||||||
const original = (
|
const original = (
|
||||||
<SizeAtPrice
|
<SizeAtPrice
|
||||||
@ -245,11 +298,11 @@ const CancelOrderDetails = ({
|
|||||||
const { data: orderById } = useOrderByIdQuery({
|
const { data: orderById } = useOrderByIdQuery({
|
||||||
variables: { orderId },
|
variables: { orderId },
|
||||||
});
|
});
|
||||||
const { data: markets } = useMarketList();
|
const { data: markets } = useMarketsMapProvider();
|
||||||
|
|
||||||
const originalOrder = orderById?.orderByID;
|
const originalOrder = orderById?.orderByID;
|
||||||
if (!originalOrder) return null;
|
if (!originalOrder) return null;
|
||||||
const market = markets?.find((m) => m.id === originalOrder.market.id);
|
const market = markets?.[originalOrder.market.id];
|
||||||
if (!market) return null;
|
if (!market) return null;
|
||||||
|
|
||||||
const original = (
|
const original = (
|
||||||
@ -282,15 +335,52 @@ const CancelOrderDetails = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CancelStopOrderDetails = ({ stopOrderId }: { stopOrderId: string }) => {
|
||||||
|
const { data: orderById } = useStopOrderByIdQuery({
|
||||||
|
variables: { stopOrderId },
|
||||||
|
});
|
||||||
|
const { data: markets } = useMarketsMapProvider();
|
||||||
|
|
||||||
|
const originalOrder = orderById?.stopOrder;
|
||||||
|
if (!originalOrder) return null;
|
||||||
|
const market = markets?.[originalOrder.marketId];
|
||||||
|
if (!market) return null;
|
||||||
|
|
||||||
|
const original = (
|
||||||
|
<>
|
||||||
|
<SizeAtPrice
|
||||||
|
side={originalOrder.submission.side}
|
||||||
|
size={originalOrder.submission.size}
|
||||||
|
price={originalOrder.submission.price}
|
||||||
|
meta={{
|
||||||
|
positionDecimalPlaces: market.positionDecimalPlaces,
|
||||||
|
decimalPlaces: market.decimalPlaces,
|
||||||
|
asset:
|
||||||
|
market.tradableInstrument.instrument.product.settlementAsset.symbol,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
{formatTrigger(originalOrder, market.decimalPlaces, '')}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<Panel title={stopOrderId}>
|
||||||
|
<h4>{t('Cancel stop order')}</h4>
|
||||||
|
<p>{market?.tradableInstrument.instrument.code}</p>
|
||||||
|
<p>
|
||||||
|
<s>{original}</s>
|
||||||
|
</p>
|
||||||
|
</Panel>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
|
export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
|
||||||
const { data: assets } = useAssetsDataProvider();
|
const { data: assets } = useAssetsMapProvider();
|
||||||
const { data: markets } = useMarketList();
|
const { data: markets } = useMarketsMapProvider();
|
||||||
|
|
||||||
if (isWithdrawTransaction(tx.body)) {
|
if (isWithdrawTransaction(tx.body)) {
|
||||||
const transactionDetails = tx.body;
|
const transactionDetails = tx.body;
|
||||||
const asset = assets?.find(
|
const asset = assets?.[transactionDetails.withdrawSubmission.asset];
|
||||||
(a) => a.id === transactionDetails.withdrawSubmission.asset
|
|
||||||
);
|
|
||||||
if (asset) {
|
if (asset) {
|
||||||
const num = formatNumber(
|
const num = formatNumber(
|
||||||
toBigNum(transactionDetails.withdrawSubmission.amount, asset.decimals),
|
toBigNum(transactionDetails.withdrawSubmission.amount, asset.decimals),
|
||||||
@ -312,15 +402,11 @@ export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOrderCancellationTransaction(tx.body)) {
|
if (isStopOrdersSubmissionTransaction(tx.body)) {
|
||||||
// CANCEL ALL (from Portfolio)
|
return <SubmitStopOrderDetails data={tx.body.stopOrdersSubmission} />;
|
||||||
if (
|
}
|
||||||
tx.body.orderCancellation.marketId === undefined &&
|
|
||||||
tx.body.orderCancellation.orderId === undefined
|
|
||||||
) {
|
|
||||||
return <Panel>{t('Cancel all orders')}</Panel>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (isOrderCancellationTransaction(tx.body)) {
|
||||||
// CANCEL
|
// CANCEL
|
||||||
if (
|
if (
|
||||||
tx.body.orderCancellation.orderId &&
|
tx.body.orderCancellation.orderId &&
|
||||||
@ -336,22 +422,50 @@ export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
|
|||||||
|
|
||||||
// CANCEL ALL (from Trading)
|
// CANCEL ALL (from Trading)
|
||||||
if (tx.body.orderCancellation.marketId) {
|
if (tx.body.orderCancellation.marketId) {
|
||||||
const marketName = markets?.find(
|
const marketName =
|
||||||
(m) =>
|
markets?.[tx.body.orderCancellation.marketId]?.tradableInstrument
|
||||||
m.id === (tx.body as OrderCancellationBody).orderCancellation.marketId
|
.instrument.code;
|
||||||
)?.tradableInstrument.instrument.code;
|
if (marketName) {
|
||||||
|
return (
|
||||||
|
<Panel>
|
||||||
|
{t('Cancel all orders for')} <strong>{marketName}</strong>
|
||||||
|
</Panel>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// CANCEL ALL (from Portfolio)
|
||||||
|
return <Panel>{t('Cancel all orders')}</Panel>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStopOrdersCancellationTransaction(tx.body)) {
|
||||||
|
// CANCEL
|
||||||
|
if (
|
||||||
|
tx.body.stopOrdersCancellation.stopOrderId &&
|
||||||
|
tx.body.stopOrdersCancellation.marketId
|
||||||
|
) {
|
||||||
return (
|
return (
|
||||||
<Panel>
|
<CancelStopOrderDetails
|
||||||
{marketName ? (
|
stopOrderId={String(tx.body.stopOrdersCancellation.stopOrderId)}
|
||||||
<>
|
/>
|
||||||
{t('Cancel all orders for')} <strong>{marketName}</strong>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
t('Cancel all orders')
|
|
||||||
)}
|
|
||||||
</Panel>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CANCEL ALL for market
|
||||||
|
if (tx.body.stopOrdersCancellation.marketId) {
|
||||||
|
const marketName =
|
||||||
|
markets?.[tx.body.stopOrdersCancellation.marketId]?.tradableInstrument
|
||||||
|
.instrument.code;
|
||||||
|
if (marketName) {
|
||||||
|
return (
|
||||||
|
<Panel>
|
||||||
|
{t('Cancel all stop orders for')} <strong>{marketName}</strong>
|
||||||
|
</Panel>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CANCEL ALL
|
||||||
|
return <Panel>{t('Cancel all stop orders')}</Panel>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOrderAmendmentTransaction(tx.body)) {
|
if (isOrderAmendmentTransaction(tx.body)) {
|
||||||
@ -368,7 +482,7 @@ export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
|
|||||||
const marketId = first(
|
const marketId = first(
|
||||||
transaction.batchMarketInstructions.cancellations
|
transaction.batchMarketInstructions.cancellations
|
||||||
)?.marketId;
|
)?.marketId;
|
||||||
const market = marketId && markets?.find((m) => m.id === marketId);
|
const market = markets?.[marketId || ''];
|
||||||
if (market) {
|
if (market) {
|
||||||
return (
|
return (
|
||||||
<Panel>
|
<Panel>
|
||||||
@ -385,7 +499,7 @@ export const VegaTransactionDetails = ({ tx }: { tx: VegaStoredTxState }) => {
|
|||||||
|
|
||||||
if (isTransferTransaction(tx.body)) {
|
if (isTransferTransaction(tx.body)) {
|
||||||
const { amount, to, asset } = tx.body.transfer;
|
const { amount, to, asset } = tx.body.transfer;
|
||||||
const transferAsset = assets?.find((a) => a.id === asset);
|
const transferAsset = assets?.[asset];
|
||||||
// only render if we have an asset to avoid unformatted amounts showing
|
// only render if we have an asset to avoid unformatted amounts showing
|
||||||
if (transferAsset) {
|
if (transferAsset) {
|
||||||
const value = addDecimalsFormatNumber(amount, transferAsset.decimals);
|
const value = addDecimalsFormatNumber(amount, transferAsset.decimals);
|
||||||
|
Loading…
Reference in New Issue
Block a user