Feat/470 edit order (#742)
* feat: 470 edit orders hook and @vegaprotocol/vegawallet-service-api-client@0.4.14 * fix: 470 add methods for dialog intent and title * fix: #657 rename order-list lib to orders * chore: #657 move hooks to orders lib * chore: #657 vega tx dialog used for order cancellation and order submission * chore: #657 use client subscribe and unsubscribe on reset, refactor vegatxdialog * fix: #657 revert script src=./env-config.js ending * fix: #657 format project.json * Update project.json * fix: #657 cancel all subs and async tasks in useffect cleanup function * feat: #657 styling updates on vega order dialog * fix: #657 rename set dialog open and awaiting confirmation dialog update * fix: #657 updates on cancel order id check * fix: #657 fix vega tx dialog test * fix: #657 fix cypress trading-deal-tciket test * fix: #657 fix data-testid market test * fix: #470 add use order edit hook * fix: #470 edit order button * Update libs/orders/README.md Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com> * Update libs/wallet/src/vega-order-transaction-dialog/vega-order-transaction-dialog.tsx Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com> * Update libs/wallet/src/vega-transaction-dialog/vega-transaction-dialog.tsx Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com> * Update libs/wallet/src/vega-order-transaction-dialog/vega-order-transaction-dialog.tsx Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com> * Update libs/wallet/src/vega-order-transaction-dialog/vega-order-transaction-dialog.tsx Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com> * fix: #657 remove the magic string and use the ordertype enum from types package * fix: #657 guarantee that order.id is present at this point or we need to determine the id of the order * fix: #657 fix translation in dialog * fix: #657 rename wallet types, delete ticket query, set finalized order null in submit * fix: #657 fix deal ticket steps test * fix: #657 remove settings.json * fix: #657 use order submit in orders lib * fix: #470 open edit order modal and update storybook * feat: #470 edit modals set up * fix: #463 final modal links to block explorer * fix: #745 long/short instead of buy/sell * fix: #657 use only one vega tx dialog * fix: #657 keep ref of subscription and unsubscribe * fix: #657 hide cancelled orders * fix: #657 sub only when id set * fix: WIP: trying to unsub when order updated * fix: #745 long/short instead of buy/sell * fix: ensure observable defined * fix: #657 remove redundant test * fix: #470 merge with new order hooks * fix: #470 fix use-order-edit no red update order-list with code * fix: #470 invert order show price last in dialog * fix: #470 able to edit order * fix: #470 fix dialog transition * fix: #656 #609 show Continuous trading and market state from trade grid header * fix: #603 filter out rejected markets * fix: #603 filter out rejected markets * fix: #470 revert to 17.0.2 react * fix: #470 revert to 17.0.2 react * fix: #603 filter out rejected markets & dialog lg width * fix: #609 show trading mode Continuous Trading and hide market state * fix: #656 modify order validation to trade when suspended * fix: #656 fix use order validation tests * fix: #656 format volume no * fix: format volume with positionDecimalPlaces * fix: tests don't need to be async * fix: md:w-[720px] to prevent dialog overflow * fix: add market state translations * fix: imprt type validation props * fix: #470 working edit submit on GTC not on GTT as it is missing expiresAt * Update libs/orders/src/lib/order-hooks/use-order-validation.tsx Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com> * Update libs/orders/src/lib/order-hooks/use-order-validation.tsx Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com> * Update libs/orders/src/lib/order-hooks/use-order-validation.tsx Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com> * Update libs/orders/src/lib/order-hooks/use-order-validation.tsx Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com> * Update libs/orders/src/lib/order-hooks/use-order-validation.tsx Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com> * Update libs/orders/src/lib/order-hooks/use-order-validation.spec.tsx Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com> * Update apps/trading/pages/markets/__generated__/Market.ts Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com> * fix: fix warning messages based on feedback * fix: capitalize trading mode * fix: capitalize trading mode * fix: remove line 72 on markets.cy.ts * fix: don't show trigger if unspecified * fix: format last price and shrink 0 on warning icon * fix: order sizes must be whole numbers for this market and input warning size 20 * fix: order sizes must be whole numbers for this market and input warning size 20 * fix: format market list * fix: #470 fix expiresAt and price unmarshall values * fix: #470 fix expiresAt and price unmarshall values * fix: #470 add extra test on editing order * fix: pass child react node for order edit on vega tx default * fix: status and rejection reason optional * fix: add header transalations and remove commented line * fix: simplify get list of markets * fix: check if order.market undefined * fix: remove cast and check market id Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com> Co-authored-by: Matthew Russell <mattrussell36@gmail.com> Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
This commit is contained in:
parent
4670d5e6cf
commit
c0532a8507
@ -1,5 +1,4 @@
|
|||||||
import { gql, useQuery } from '@apollo/client';
|
import { gql, useQuery } from '@apollo/client';
|
||||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
|
||||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
import orderBy from 'lodash/orderBy';
|
import orderBy from 'lodash/orderBy';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
@ -20,15 +19,13 @@ const MARKETS_QUERY = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const marketList = ({ markets }: MarketsLanding) =>
|
const getMarketList = ({ markets = [] }: MarketsLanding) => {
|
||||||
orderBy(
|
return orderBy(
|
||||||
markets?.filter(
|
markets,
|
||||||
({ marketTimestamps, tradingMode }) =>
|
['marketTimestamps.open', 'id'],
|
||||||
marketTimestamps.open && tradingMode === MarketTradingMode.Continuous
|
|
||||||
) || [],
|
|
||||||
['state', 'marketTimestamps.open', 'id'],
|
|
||||||
['asc', 'asc', 'asc']
|
['asc', 'asc', 'asc']
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export function Index() {
|
export function Index() {
|
||||||
const { replace } = useRouter();
|
const { replace } = useRouter();
|
||||||
@ -39,7 +36,7 @@ export function Index() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
const marketId = marketList(data)[0]?.id;
|
const marketId = getMarketList(data)[0]?.id;
|
||||||
|
|
||||||
// If a default market is found, go to it with the landing dialog open
|
// If a default market is found, go to it with the landing dialog open
|
||||||
if (marketId) {
|
if (marketId) {
|
||||||
|
102
libs/orders/src/lib/components/order-list/order-edit-dialog.tsx
Normal file
102
libs/orders/src/lib/components/order-list/order-edit-dialog.tsx
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import {
|
||||||
|
addDecimal,
|
||||||
|
t,
|
||||||
|
addDecimalsFormatNumber,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
|
import { OrderType } from '@vegaprotocol/types';
|
||||||
|
import { FormGroup, Input, InputError, Button } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import Icon from 'react-syntax-highlighter';
|
||||||
|
import { OrderDialogWrapper } from '@vegaprotocol/wallet';
|
||||||
|
import type { Order } from '@vegaprotocol/wallet';
|
||||||
|
|
||||||
|
interface OrderEditDialogProps {
|
||||||
|
title: string;
|
||||||
|
order: Order | null;
|
||||||
|
edit: (body: Order) => Promise<unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormFields {
|
||||||
|
entryPrice: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OrderEditDialog = ({
|
||||||
|
order,
|
||||||
|
title,
|
||||||
|
edit,
|
||||||
|
}: OrderEditDialogProps) => {
|
||||||
|
const headerClassName = 'text-h5 font-bold text-black dark:text-white';
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
formState: { errors },
|
||||||
|
handleSubmit,
|
||||||
|
} = useForm<FormFields>({
|
||||||
|
defaultValues: {
|
||||||
|
entryPrice: order?.price
|
||||||
|
? addDecimal(order?.price, order?.market?.decimalPlaces ?? 0)
|
||||||
|
: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!order) return null;
|
||||||
|
return (
|
||||||
|
<OrderDialogWrapper title={title} icon={<Icon name="hand-up" size={20} />}>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||||
|
{order.market && (
|
||||||
|
<div>
|
||||||
|
<p className={headerClassName}>{t(`Market`)}</p>
|
||||||
|
<p>{t(`${order.market.name}`)}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{order.type === OrderType.Limit && order.market && (
|
||||||
|
<div>
|
||||||
|
<p className={headerClassName}>{t(`Last price`)}</p>
|
||||||
|
<p>
|
||||||
|
{addDecimalsFormatNumber(order.price, order.market.decimalPlaces)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div>
|
||||||
|
<p className={headerClassName}>{t(`Amount remaining`)}</p>
|
||||||
|
<p
|
||||||
|
className={
|
||||||
|
order.side === 'Buy'
|
||||||
|
? 'text-dark-green dark:text-vega-green'
|
||||||
|
: 'text-red dark:text-vega-red'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{order.side === 'Buy' ? '+' : '-'}
|
||||||
|
{order.size}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 py-12">
|
||||||
|
<form
|
||||||
|
onSubmit={handleSubmit(async (data) => {
|
||||||
|
await edit({
|
||||||
|
...order,
|
||||||
|
price: data.entryPrice,
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
data-testid="edit-order"
|
||||||
|
>
|
||||||
|
<FormGroup label={t('Entry price')} labelFor="entryPrice">
|
||||||
|
<Input
|
||||||
|
{...register('entryPrice', { required: t('Required') })}
|
||||||
|
id="entryPrice"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
{errors.entryPrice?.message && (
|
||||||
|
<InputError intent="danger" className="mt-4">
|
||||||
|
{errors.entryPrice.message}
|
||||||
|
</InputError>
|
||||||
|
)}
|
||||||
|
</FormGroup>
|
||||||
|
<Button variant="primary" type="submit">
|
||||||
|
{t('Update')}
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</OrderDialogWrapper>
|
||||||
|
);
|
||||||
|
};
|
@ -16,7 +16,12 @@ const generateJsx = (
|
|||||||
return (
|
return (
|
||||||
<MockedProvider>
|
<MockedProvider>
|
||||||
<VegaWalletContext.Provider value={context as VegaWalletContextShape}>
|
<VegaWalletContext.Provider value={context as VegaWalletContextShape}>
|
||||||
<OrderListTable data={orders} cancel={jest.fn()} />
|
<OrderListTable
|
||||||
|
data={orders}
|
||||||
|
cancel={jest.fn()}
|
||||||
|
setEditOrderDialogOpen={jest.fn()}
|
||||||
|
setEditOrder={jest.fn()}
|
||||||
|
/>
|
||||||
</VegaWalletContext.Provider>
|
</VegaWalletContext.Provider>
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
);
|
);
|
||||||
@ -36,7 +41,7 @@ describe('OrderListTable', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const headers = screen.getAllByRole('columnheader');
|
const headers = screen.getAllByRole('columnheader');
|
||||||
expect(headers).toHaveLength(10);
|
expect(headers).toHaveLength(11);
|
||||||
expect(headers.map((h) => h.textContent?.trim())).toEqual([
|
expect(headers.map((h) => h.textContent?.trim())).toEqual([
|
||||||
'Market',
|
'Market',
|
||||||
'Amount',
|
'Amount',
|
||||||
@ -47,6 +52,7 @@ describe('OrderListTable', () => {
|
|||||||
'Time In Force',
|
'Time In Force',
|
||||||
'Created At',
|
'Created At',
|
||||||
'Updated At',
|
'Updated At',
|
||||||
|
'Edit',
|
||||||
'Cancel',
|
'Cancel',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
@ -67,6 +73,7 @@ describe('OrderListTable', () => {
|
|||||||
marketOrder.timeInForce,
|
marketOrder.timeInForce,
|
||||||
getDateTimeFormat().format(new Date(marketOrder.createdAt)),
|
getDateTimeFormat().format(new Date(marketOrder.createdAt)),
|
||||||
'-',
|
'-',
|
||||||
|
'Edit',
|
||||||
'Cancel',
|
'Cancel',
|
||||||
];
|
];
|
||||||
cells.forEach((cell, i) =>
|
cells.forEach((cell, i) =>
|
||||||
@ -92,6 +99,7 @@ describe('OrderListTable', () => {
|
|||||||
)}`,
|
)}`,
|
||||||
getDateTimeFormat().format(new Date(limitOrder.createdAt)),
|
getDateTimeFormat().format(new Date(limitOrder.createdAt)),
|
||||||
'-',
|
'-',
|
||||||
|
'Edit',
|
||||||
'Cancel',
|
'Cancel',
|
||||||
];
|
];
|
||||||
cells.forEach((cell, i) =>
|
cells.forEach((cell, i) =>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { Story, Meta } from '@storybook/react';
|
import type { Story, Meta } from '@storybook/react';
|
||||||
import { OrderType, OrderStatus } from '@vegaprotocol/types';
|
import { OrderType, OrderStatus, OrderTimeInForce } from '@vegaprotocol/types';
|
||||||
import { OrderList, OrderListTable } from './order-list';
|
import { OrderList, OrderListTable } from './order-list';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import type { Order, VegaTxState } from '@vegaprotocol/wallet';
|
import type { Order, VegaTxState } from '@vegaprotocol/wallet';
|
||||||
@ -15,7 +15,16 @@ const Template: Story = (args) => {
|
|||||||
const cancel = () => Promise.resolve();
|
const cancel = () => Promise.resolve();
|
||||||
return (
|
return (
|
||||||
<div style={{ height: 1000 }}>
|
<div style={{ height: 1000 }}>
|
||||||
<OrderListTable data={args.data} cancel={cancel} />
|
<OrderListTable
|
||||||
|
data={args.data}
|
||||||
|
cancel={cancel}
|
||||||
|
setEditOrderDialogOpen={() => {
|
||||||
|
return;
|
||||||
|
}}
|
||||||
|
setEditOrder={() => {
|
||||||
|
return;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -39,12 +48,22 @@ const Template2: Story = (args) => {
|
|||||||
price: '1000',
|
price: '1000',
|
||||||
market: { name: 'ETH/DAI (30 Jun 2022)', decimalPlaces: 5 },
|
market: { name: 'ETH/DAI (30 Jun 2022)', decimalPlaces: 5 },
|
||||||
type: OrderType.Limit,
|
type: OrderType.Limit,
|
||||||
|
timeInForce: OrderTimeInForce.GTC,
|
||||||
};
|
};
|
||||||
const reset = () => null;
|
const reset = () => null;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div style={{ height: 1000 }}>
|
<div style={{ height: 1000 }}>
|
||||||
<OrderListTable data={args.data} cancel={cancel} />
|
<OrderListTable
|
||||||
|
data={args.data}
|
||||||
|
cancel={cancel}
|
||||||
|
setEditOrderDialogOpen={() => {
|
||||||
|
return;
|
||||||
|
}}
|
||||||
|
setEditOrder={() => {
|
||||||
|
return;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<VegaTransactionDialog
|
<VegaTransactionDialog
|
||||||
orderDialogOpen={open}
|
orderDialogOpen={open}
|
||||||
|
@ -12,6 +12,8 @@ import { forwardRef, useState } from 'react';
|
|||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { useOrderCancel } from '../../order-hooks/use-order-cancel';
|
import { useOrderCancel } from '../../order-hooks/use-order-cancel';
|
||||||
import { VegaTransactionDialog } from '@vegaprotocol/wallet';
|
import { VegaTransactionDialog } from '@vegaprotocol/wallet';
|
||||||
|
import { useOrderEdit } from '../../order-hooks/use-order-edit';
|
||||||
|
import { OrderEditDialog } from './order-edit-dialog';
|
||||||
|
|
||||||
interface OrderListProps {
|
interface OrderListProps {
|
||||||
data: Orders_party_orders[] | null;
|
data: Orders_party_orders[] | null;
|
||||||
@ -21,11 +23,22 @@ interface OrderListProps {
|
|||||||
export const OrderList = forwardRef<AgGridReact, OrderListProps>(
|
export const OrderList = forwardRef<AgGridReact, OrderListProps>(
|
||||||
({ data, showCancelled = true }, ref) => {
|
({ data, showCancelled = true }, ref) => {
|
||||||
const [cancelOrderDialogOpen, setCancelOrderDialogOpen] = useState(false);
|
const [cancelOrderDialogOpen, setCancelOrderDialogOpen] = useState(false);
|
||||||
|
const [editOrderDialogOpen, setEditOrderDialogOpen] = useState(false);
|
||||||
|
const [editOrder, setEditOrder] = useState<Orders_party_orders | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
const { transaction, updatedOrder, reset, cancel } = useOrderCancel();
|
const { transaction, updatedOrder, reset, cancel } = useOrderCancel();
|
||||||
|
const {
|
||||||
|
transaction: editTransaction,
|
||||||
|
updatedOrder: editedOrder,
|
||||||
|
reset: resetEdit,
|
||||||
|
edit,
|
||||||
|
} = useOrderEdit();
|
||||||
const ordersData = showCancelled
|
const ordersData = showCancelled
|
||||||
? data
|
? data
|
||||||
: data?.filter((o) => o.status !== OrderStatus.Cancelled) || null;
|
: data?.filter((o) => o.status !== OrderStatus.Cancelled) || null;
|
||||||
const getDialogTitle = (status?: string) => {
|
const getCancelDialogTitle = (status?: string) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case OrderStatus.Cancelled:
|
case OrderStatus.Cancelled:
|
||||||
return 'Order cancelled';
|
return 'Order cancelled';
|
||||||
@ -37,18 +50,51 @@ export const OrderList = forwardRef<AgGridReact, OrderListProps>(
|
|||||||
return 'Cancellation failed';
|
return 'Cancellation failed';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const getEditDialogTitle = () =>
|
||||||
|
editedOrder
|
||||||
|
? t(
|
||||||
|
`Order ${
|
||||||
|
editOrder?.market?.tradableInstrument.instrument.code ?? ''
|
||||||
|
} updated`
|
||||||
|
)
|
||||||
|
: t(
|
||||||
|
`Edit ${
|
||||||
|
editOrder?.market?.tradableInstrument.instrument.code ?? ''
|
||||||
|
} order`
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<OrderListTable data={ordersData} cancel={cancel} ref={ref} />
|
<OrderListTable
|
||||||
|
data={ordersData}
|
||||||
|
cancel={cancel}
|
||||||
|
ref={ref}
|
||||||
|
setEditOrderDialogOpen={setEditOrderDialogOpen}
|
||||||
|
setEditOrder={setEditOrder}
|
||||||
|
/>
|
||||||
<VegaTransactionDialog
|
<VegaTransactionDialog
|
||||||
key={`cancel-order-dialog-${transaction.txHash}`}
|
key={`cancel-order-dialog-${transaction.txHash}`}
|
||||||
orderDialogOpen={cancelOrderDialogOpen}
|
orderDialogOpen={cancelOrderDialogOpen}
|
||||||
setOrderDialogOpen={setCancelOrderDialogOpen}
|
setOrderDialogOpen={setCancelOrderDialogOpen}
|
||||||
finalizedOrder={updatedOrder}
|
|
||||||
transaction={transaction}
|
transaction={transaction}
|
||||||
reset={reset}
|
reset={reset}
|
||||||
title={getDialogTitle(updatedOrder?.status)}
|
title={getCancelDialogTitle(updatedOrder?.status)}
|
||||||
|
finalizedOrder={updatedOrder}
|
||||||
/>
|
/>
|
||||||
|
<VegaTransactionDialog
|
||||||
|
key={`edit-order-dialog-${transaction.txHash}`}
|
||||||
|
orderDialogOpen={editOrderDialogOpen}
|
||||||
|
setOrderDialogOpen={setEditOrderDialogOpen}
|
||||||
|
transaction={editTransaction}
|
||||||
|
reset={resetEdit}
|
||||||
|
title={getEditDialogTitle()}
|
||||||
|
finalizedOrder={editedOrder}
|
||||||
|
>
|
||||||
|
<OrderEditDialog
|
||||||
|
title={getEditDialogTitle()}
|
||||||
|
order={editOrder}
|
||||||
|
edit={edit}
|
||||||
|
/>
|
||||||
|
</VegaTransactionDialog>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -57,10 +103,12 @@ export const OrderList = forwardRef<AgGridReact, OrderListProps>(
|
|||||||
interface OrderListTableProps {
|
interface OrderListTableProps {
|
||||||
data: Orders_party_orders[] | null;
|
data: Orders_party_orders[] | null;
|
||||||
cancel: (body?: unknown) => Promise<unknown>;
|
cancel: (body?: unknown) => Promise<unknown>;
|
||||||
|
setEditOrderDialogOpen: (value: boolean) => void;
|
||||||
|
setEditOrder: (order: Orders_party_orders | null) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
||||||
({ data, cancel }, ref) => {
|
({ data, cancel, setEditOrderDialogOpen, setEditOrder }, ref) => {
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@ -147,6 +195,34 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
|||||||
return value ? getDateTimeFormat().format(new Date(value)) : '-';
|
return value ? getDateTimeFormat().format(new Date(value)) : '-';
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<AgGridColumn
|
||||||
|
field="edit"
|
||||||
|
cellRenderer={({ data }: ICellRendererParams) => {
|
||||||
|
if (
|
||||||
|
![
|
||||||
|
OrderStatus.Cancelled,
|
||||||
|
OrderStatus.Rejected,
|
||||||
|
OrderStatus.Expired,
|
||||||
|
OrderStatus.Filled,
|
||||||
|
OrderStatus.Stopped,
|
||||||
|
].includes(data.status)
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
data-testid="edit"
|
||||||
|
variant="secondary"
|
||||||
|
onClick={() => {
|
||||||
|
setEditOrderDialogOpen(true);
|
||||||
|
setEditOrder(data);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
field="cancel"
|
field="cancel"
|
||||||
cellRenderer={({ data }: ICellRendererParams) => {
|
cellRenderer={({ data }: ICellRendererParams) => {
|
||||||
|
@ -15,6 +15,10 @@ export interface OrderEvent_busEvents_event_TimeUpdate {
|
|||||||
|
|
||||||
export interface OrderEvent_busEvents_event_Order_market {
|
export interface OrderEvent_busEvents_event_Order_market {
|
||||||
__typename: "Market";
|
__typename: "Market";
|
||||||
|
/**
|
||||||
|
* Market ID
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
/**
|
/**
|
||||||
* Market full name
|
* Market full name
|
||||||
*/
|
*/
|
||||||
|
@ -14,8 +14,10 @@ export const ORDER_EVENT_SUB = gql`
|
|||||||
size
|
size
|
||||||
price
|
price
|
||||||
timeInForce
|
timeInForce
|
||||||
|
expiresAt
|
||||||
side
|
side
|
||||||
market {
|
market {
|
||||||
|
id
|
||||||
name
|
name
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ export const useOrderCancel = () => {
|
|||||||
if (res?.signature) {
|
if (res?.signature) {
|
||||||
const resId = order.id ?? determineId(res.signature);
|
const resId = order.id ?? determineId(res.signature);
|
||||||
setUpdatedOrder(null);
|
setUpdatedOrder(null);
|
||||||
// setId(resId);
|
|
||||||
if (resId) {
|
if (resId) {
|
||||||
// Start a subscription looking for the newly created order
|
// Start a subscription looking for the newly created order
|
||||||
subRef.current = client
|
subRef.current = client
|
||||||
|
221
libs/orders/src/lib/order-hooks/use-order-edit.spec.tsx
Normal file
221
libs/orders/src/lib/order-hooks/use-order-edit.spec.tsx
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
import { act, renderHook } from '@testing-library/react-hooks';
|
||||||
|
import type {
|
||||||
|
VegaKeyExtended,
|
||||||
|
VegaWalletContextShape,
|
||||||
|
} from '@vegaprotocol/wallet';
|
||||||
|
import {
|
||||||
|
VegaWalletOrderSide,
|
||||||
|
VegaWalletOrderTimeInForce,
|
||||||
|
VegaWalletOrderType,
|
||||||
|
} from '@vegaprotocol/wallet';
|
||||||
|
import { VegaTxStatus, VegaWalletContext } from '@vegaprotocol/wallet';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import { useOrderEdit } from './use-order-edit';
|
||||||
|
import type {
|
||||||
|
OrderEvent,
|
||||||
|
OrderEvent_busEvents,
|
||||||
|
} from './__generated__/OrderEvent';
|
||||||
|
import { ORDER_EVENT_SUB } from './order-event-query';
|
||||||
|
import type { MockedResponse } from '@apollo/client/testing';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import {
|
||||||
|
MarketTradingMode,
|
||||||
|
MarketState,
|
||||||
|
OrderTimeInForce,
|
||||||
|
} from '@vegaprotocol/types';
|
||||||
|
import type {
|
||||||
|
OrderAmendmentBodyOrderAmendment,
|
||||||
|
OrderAmendmentBody,
|
||||||
|
} from '@vegaprotocol/vegawallet-service-api-client';
|
||||||
|
|
||||||
|
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>) {
|
||||||
|
const mocks: MockedResponse<OrderEvent> = {
|
||||||
|
request: {
|
||||||
|
query: ORDER_EVENT_SUB,
|
||||||
|
variables: {
|
||||||
|
partyId: context?.keypair?.pub || '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
busEvents: [
|
||||||
|
{
|
||||||
|
type: 'Order',
|
||||||
|
event: {
|
||||||
|
type: 'Limit',
|
||||||
|
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
|
||||||
|
status: 'Active',
|
||||||
|
rejectionReason: null,
|
||||||
|
createdAt: '2022-07-05T14:25:47.815283706Z',
|
||||||
|
size: '10',
|
||||||
|
price: '300000',
|
||||||
|
timeInForce: 'GTC',
|
||||||
|
side: 'Buy',
|
||||||
|
market: {
|
||||||
|
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||||
|
decimalPlaces: 5,
|
||||||
|
__typename: 'Market',
|
||||||
|
},
|
||||||
|
__typename: 'Order',
|
||||||
|
},
|
||||||
|
__typename: 'BusEvent',
|
||||||
|
} as OrderEvent_busEvents,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const filterMocks: MockedResponse<OrderEvent> = {
|
||||||
|
request: {
|
||||||
|
query: ORDER_EVENT_SUB,
|
||||||
|
variables: {
|
||||||
|
partyId: context?.keypair?.pub || '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
busEvents: [
|
||||||
|
{
|
||||||
|
type: 'Order',
|
||||||
|
event: {
|
||||||
|
type: 'Limit',
|
||||||
|
id: '9c70716f6c3698ac7bbcddc97176025b985a6bb9a0c4507ec09c9960b3216b62',
|
||||||
|
status: 'Active',
|
||||||
|
rejectionReason: null,
|
||||||
|
createdAt: '2022-07-05T14:25:47.815283706Z',
|
||||||
|
size: '10',
|
||||||
|
price: '300000',
|
||||||
|
timeInForce: 'GTC',
|
||||||
|
side: 'Buy',
|
||||||
|
market: {
|
||||||
|
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||||
|
decimalPlaces: 5,
|
||||||
|
__typename: 'Market',
|
||||||
|
},
|
||||||
|
__typename: 'Order',
|
||||||
|
},
|
||||||
|
__typename: 'BusEvent',
|
||||||
|
} as OrderEvent_busEvents,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||||
|
<MockedProvider mocks={[mocks, filterMocks]}>
|
||||||
|
<VegaWalletContext.Provider
|
||||||
|
value={{ ...defaultWalletContext, ...context }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</VegaWalletContext.Provider>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
return renderHook(() => useOrderEdit(), { wrapper });
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultMarket = {
|
||||||
|
__typename: 'Market',
|
||||||
|
id: 'market-id',
|
||||||
|
decimalPlaces: 2,
|
||||||
|
positionDecimalPlaces: 1,
|
||||||
|
tradingMode: MarketTradingMode.Continuous,
|
||||||
|
state: MarketState.Active,
|
||||||
|
tradableInstrument: {
|
||||||
|
__typename: 'TradableInstrument',
|
||||||
|
instrument: {
|
||||||
|
__typename: 'Instrument',
|
||||||
|
product: {
|
||||||
|
__typename: 'Future',
|
||||||
|
quoteName: 'quote-name',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
depth: {
|
||||||
|
__typename: 'MarketDepth',
|
||||||
|
lastTrade: {
|
||||||
|
__typename: 'Trade',
|
||||||
|
price: '100',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const order = {
|
||||||
|
id: 'order-id',
|
||||||
|
type: VegaWalletOrderType.Limit,
|
||||||
|
size: '10',
|
||||||
|
timeInForce: OrderTimeInForce.GTT, // order timeInForce is transformed to wallet timeInForce
|
||||||
|
side: VegaWalletOrderSide.Buy,
|
||||||
|
price: '1234567.89',
|
||||||
|
expiration: new Date('2022-01-01'),
|
||||||
|
expiresAt: new Date('2022-01-01'),
|
||||||
|
status: VegaTxStatus.Pending,
|
||||||
|
rejectionReason: null,
|
||||||
|
market: {
|
||||||
|
id: 'market-id',
|
||||||
|
decimalPlaces: 2,
|
||||||
|
name: 'ETHDAI',
|
||||||
|
positionDecimalPlaces: 2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('useOrderEdit', () => {
|
||||||
|
it('should edit a correctly formatted order', async () => {
|
||||||
|
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve({}));
|
||||||
|
const keypair = {
|
||||||
|
pub: '0x123',
|
||||||
|
} as VegaKeyExtended;
|
||||||
|
const { result } = setup({
|
||||||
|
sendTx: mockSendTx,
|
||||||
|
keypairs: [keypair],
|
||||||
|
keypair,
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
result.current.edit(order);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockSendTx).toHaveBeenCalledWith({
|
||||||
|
pubKey: keypair.pub,
|
||||||
|
propagate: true,
|
||||||
|
orderAmendment: {
|
||||||
|
orderId: 'order-id',
|
||||||
|
marketId: defaultMarket.id, // Market provided from hook argument
|
||||||
|
timeInForce: VegaWalletOrderTimeInForce.GTT,
|
||||||
|
price: { value: '123456789' }, // Decimal removed
|
||||||
|
sizeDelta: 0,
|
||||||
|
expiresAt: { value: order.expiration?.getTime() + '000000' }, // Nanoseconds append
|
||||||
|
} as unknown as OrderAmendmentBodyOrderAmendment,
|
||||||
|
} as OrderAmendmentBody);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has the correct default state', () => {
|
||||||
|
const { result } = setup();
|
||||||
|
expect(typeof result.current.edit).toEqual('function');
|
||||||
|
expect(typeof result.current.reset).toEqual('function');
|
||||||
|
expect(result.current.transaction.status).toEqual(VegaTxStatus.Default);
|
||||||
|
expect(result.current.transaction.txHash).toEqual(null);
|
||||||
|
expect(result.current.transaction.error).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not sendTx if no keypair', async () => {
|
||||||
|
const mockSendTx = jest.fn();
|
||||||
|
const { result } = setup({
|
||||||
|
sendTx: mockSendTx,
|
||||||
|
keypairs: [],
|
||||||
|
keypair: null,
|
||||||
|
});
|
||||||
|
await act(async () => {
|
||||||
|
result.current.edit(order);
|
||||||
|
});
|
||||||
|
expect(mockSendTx).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
119
libs/orders/src/lib/order-hooks/use-order-edit.tsx
Normal file
119
libs/orders/src/lib/order-hooks/use-order-edit.tsx
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import { useApolloClient } from '@apollo/client';
|
||||||
|
import { determineId, removeDecimal } from '@vegaprotocol/react-helpers';
|
||||||
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
||||||
|
import type { Order } from '@vegaprotocol/wallet';
|
||||||
|
import { VegaWalletOrderTimeInForce } from '@vegaprotocol/wallet';
|
||||||
|
import { useVegaTransaction, useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
import { ORDER_EVENT_SUB } from './order-event-query';
|
||||||
|
import type { Subscription } from 'zen-observable-ts';
|
||||||
|
import type {
|
||||||
|
OrderEvent_busEvents_event_Order,
|
||||||
|
OrderEvent,
|
||||||
|
OrderEventVariables,
|
||||||
|
} from './__generated__';
|
||||||
|
import * as Sentry from '@sentry/react';
|
||||||
|
|
||||||
|
export const useOrderEdit = () => {
|
||||||
|
const { keypair } = useVegaWallet();
|
||||||
|
const { send, transaction, reset: resetTransaction } = useVegaTransaction();
|
||||||
|
const [updatedOrder, setUpdatedOrder] =
|
||||||
|
useState<OrderEvent_busEvents_event_Order | null>(null);
|
||||||
|
const client = useApolloClient();
|
||||||
|
const subRef = useRef<Subscription | null>(null);
|
||||||
|
|
||||||
|
const reset = useCallback(() => {
|
||||||
|
resetTransaction();
|
||||||
|
setUpdatedOrder(null);
|
||||||
|
subRef.current?.unsubscribe();
|
||||||
|
}, [resetTransaction]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
resetTransaction();
|
||||||
|
setUpdatedOrder(null);
|
||||||
|
subRef.current?.unsubscribe();
|
||||||
|
};
|
||||||
|
}, [resetTransaction]);
|
||||||
|
|
||||||
|
const edit = useCallback(
|
||||||
|
async (order: Order) => {
|
||||||
|
if (!keypair || !order.market || !order.market.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUpdatedOrder(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await send({
|
||||||
|
pubKey: keypair.pub,
|
||||||
|
propagate: true,
|
||||||
|
orderAmendment: {
|
||||||
|
orderId: order.id,
|
||||||
|
marketId: order.market.id,
|
||||||
|
price: {
|
||||||
|
value: removeDecimal(order.price, order.market?.decimalPlaces),
|
||||||
|
},
|
||||||
|
timeInForce: VegaWalletOrderTimeInForce[order.timeInForce],
|
||||||
|
sizeDelta: 0,
|
||||||
|
expiresAt: order.expiresAt
|
||||||
|
? {
|
||||||
|
value:
|
||||||
|
// Wallet expects timestamp in nanoseconds,
|
||||||
|
// we don't have that level of accuracy so just append 6 zeroes
|
||||||
|
new Date(order.expiresAt).getTime().toString() + '000000',
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res?.signature) {
|
||||||
|
const resId = order.id ?? determineId(res.signature);
|
||||||
|
setUpdatedOrder(null);
|
||||||
|
|
||||||
|
if (resId) {
|
||||||
|
// Start a subscription looking for the newly created order
|
||||||
|
subRef.current = client
|
||||||
|
.subscribe<OrderEvent, OrderEventVariables>({
|
||||||
|
query: ORDER_EVENT_SUB,
|
||||||
|
variables: { partyId: keypair?.pub || '' },
|
||||||
|
})
|
||||||
|
.subscribe(({ data }) => {
|
||||||
|
if (!data?.busEvents?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No types available for the subscription result
|
||||||
|
const matchingOrderEvent = data.busEvents.find((e) => {
|
||||||
|
if (e.event.__typename !== 'Order') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.event.id === resId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (
|
||||||
|
matchingOrderEvent &&
|
||||||
|
matchingOrderEvent.event.__typename === 'Order'
|
||||||
|
) {
|
||||||
|
setUpdatedOrder(matchingOrderEvent.event);
|
||||||
|
subRef.current?.unsubscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
} catch (e) {
|
||||||
|
Sentry.captureException(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[client, keypair, send]
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
transaction,
|
||||||
|
updatedOrder,
|
||||||
|
edit,
|
||||||
|
reset,
|
||||||
|
};
|
||||||
|
};
|
@ -5,6 +5,7 @@ import {
|
|||||||
} from '@vegaprotocol/wallet';
|
} from '@vegaprotocol/wallet';
|
||||||
import { toDecimal } from '@vegaprotocol/react-helpers';
|
import { toDecimal } from '@vegaprotocol/react-helpers';
|
||||||
import type { Market } from '../market';
|
import type { Market } from '../market';
|
||||||
|
import type { OrderStatus } from '@vegaprotocol/types';
|
||||||
|
|
||||||
export type Order =
|
export type Order =
|
||||||
| {
|
| {
|
||||||
@ -14,6 +15,9 @@ export type Order =
|
|||||||
side: VegaWalletOrderSide;
|
side: VegaWalletOrderSide;
|
||||||
price?: never;
|
price?: never;
|
||||||
expiration?: never;
|
expiration?: never;
|
||||||
|
rejectionReason: string | null;
|
||||||
|
status?: OrderStatus;
|
||||||
|
market?: Market | null;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
size: string;
|
size: string;
|
||||||
@ -22,6 +26,9 @@ export type Order =
|
|||||||
side: VegaWalletOrderSide;
|
side: VegaWalletOrderSide;
|
||||||
price?: string;
|
price?: string;
|
||||||
expiration?: Date;
|
expiration?: Date;
|
||||||
|
rejectionReason: string | null;
|
||||||
|
status?: OrderStatus;
|
||||||
|
market?: Market | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDefaultOrder = (market: Market): Order => ({
|
export const getDefaultOrder = (market: Market): Order => ({
|
||||||
@ -29,4 +36,6 @@ export const getDefaultOrder = (market: Market): Order => ({
|
|||||||
side: VegaWalletOrderSide.Buy,
|
side: VegaWalletOrderSide.Buy,
|
||||||
timeInForce: VegaWalletOrderTimeInForce.IOC,
|
timeInForce: VegaWalletOrderTimeInForce.IOC,
|
||||||
size: String(toDecimal(market.positionDecimalPlaces)),
|
size: String(toDecimal(market.positionDecimalPlaces)),
|
||||||
|
rejectionReason: null,
|
||||||
|
market: null,
|
||||||
});
|
});
|
||||||
|
10
libs/types/src/__generated__/globalTypes.ts
generated
10
libs/types/src/__generated__/globalTypes.ts
generated
@ -293,16 +293,6 @@ export enum WithdrawalStatus {
|
|||||||
Rejected = "Rejected",
|
Rejected = "Rejected",
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Pagination constructs to support cursor based pagination in the API
|
|
||||||
*/
|
|
||||||
export interface Pagination {
|
|
||||||
first?: number | null;
|
|
||||||
after?: string | null;
|
|
||||||
last?: number | null;
|
|
||||||
before?: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================
|
//==============================================================
|
||||||
// END Enums and Input Objects
|
// END Enums and Input Objects
|
||||||
//==============================================================
|
//==============================================================
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
export * from './__generated__/globalTypes';
|
export * from './__generated__/globalTypes';
|
||||||
export * from './candle';
|
export * from './candle';
|
||||||
|
export * from './pagination';
|
||||||
|
6
libs/types/src/pagination.ts
Normal file
6
libs/types/src/pagination.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface Pagination {
|
||||||
|
first?: number;
|
||||||
|
after?: string;
|
||||||
|
last?: number;
|
||||||
|
before?: string;
|
||||||
|
}
|
@ -17,6 +17,7 @@ export interface VegaTransactionDialogProps {
|
|||||||
transaction: VegaTxState;
|
transaction: VegaTxState;
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getDialogIntent = (
|
const getDialogIntent = (
|
||||||
@ -45,6 +46,7 @@ export const VegaTransactionDialog = ({
|
|||||||
transaction,
|
transaction,
|
||||||
reset,
|
reset,
|
||||||
title = '',
|
title = '',
|
||||||
|
children,
|
||||||
}: VegaTransactionDialogProps) => {
|
}: VegaTransactionDialogProps) => {
|
||||||
// open / close dialog
|
// open / close dialog
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -75,6 +77,7 @@ export const VegaTransactionDialog = ({
|
|||||||
transaction={transaction}
|
transaction={transaction}
|
||||||
finalizedOrder={finalizedOrder}
|
finalizedOrder={finalizedOrder}
|
||||||
title={title}
|
title={title}
|
||||||
|
children={children}
|
||||||
/>
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
@ -84,15 +87,22 @@ interface VegaDialogProps {
|
|||||||
transaction: VegaTxState;
|
transaction: VegaTxState;
|
||||||
finalizedOrder: Order | null;
|
finalizedOrder: Order | null;
|
||||||
title: string;
|
title: string;
|
||||||
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const VegaDialog = ({
|
export const VegaDialog = ({
|
||||||
transaction,
|
transaction,
|
||||||
finalizedOrder,
|
finalizedOrder,
|
||||||
title,
|
title,
|
||||||
|
children,
|
||||||
}: VegaDialogProps) => {
|
}: VegaDialogProps) => {
|
||||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||||
const headerClassName = 'text-h5 font-bold text-black dark:text-white';
|
const headerClassName = 'text-h5 font-bold text-black dark:text-white';
|
||||||
|
|
||||||
|
if (children && transaction.status === VegaTxStatus.Default) {
|
||||||
|
return <div>{children}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
// Rejected by wallet
|
// Rejected by wallet
|
||||||
if (transaction.status === VegaTxStatus.Requested) {
|
if (transaction.status === VegaTxStatus.Requested) {
|
||||||
return (
|
return (
|
||||||
@ -178,6 +188,17 @@ export const VegaDialog = ({
|
|||||||
<p className={headerClassName}>{t(`Status`)}</p>
|
<p className={headerClassName}>{t(`Status`)}</p>
|
||||||
<p>{t(`${finalizedOrder.status}`)}</p>
|
<p>{t(`${finalizedOrder.status}`)}</p>
|
||||||
</div>
|
</div>
|
||||||
|
{finalizedOrder.type === OrderType.Limit && finalizedOrder.market && (
|
||||||
|
<div>
|
||||||
|
<p className={headerClassName}>{t(`Price`)}</p>
|
||||||
|
<p>
|
||||||
|
{addDecimalsFormatNumber(
|
||||||
|
finalizedOrder.price,
|
||||||
|
finalizedOrder.market.decimalPlaces
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div>
|
<div>
|
||||||
<p className={headerClassName}>{t(`Amount`)}</p>
|
<p className={headerClassName}>{t(`Amount`)}</p>
|
||||||
<p
|
<p
|
||||||
@ -193,17 +214,6 @@ export const VegaDialog = ({
|
|||||||
`}
|
`}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{finalizedOrder.type === OrderType.Limit && finalizedOrder.market && (
|
|
||||||
<div>
|
|
||||||
<p className={headerClassName}>{t(`Price`)}</p>
|
|
||||||
<p>
|
|
||||||
{addDecimalsFormatNumber(
|
|
||||||
finalizedOrder.price,
|
|
||||||
finalizedOrder.market.decimalPlaces
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 gap-8">
|
<div className="grid grid-cols-1 gap-8">
|
||||||
{transaction.txHash && (
|
{transaction.txHash && (
|
||||||
@ -231,7 +241,7 @@ interface OrderDialogWrapperProps {
|
|||||||
title: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OrderDialogWrapper = ({
|
export const OrderDialogWrapper = ({
|
||||||
children,
|
children,
|
||||||
icon,
|
icon,
|
||||||
title,
|
title,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { OrderTimeInForce } from '@vegaprotocol/types';
|
||||||
import type {
|
import type {
|
||||||
DelegateSubmissionBody,
|
DelegateSubmissionBody,
|
||||||
OrderCancellationBody,
|
OrderCancellationBody,
|
||||||
@ -41,14 +42,18 @@ export interface Market {
|
|||||||
name: string;
|
name: string;
|
||||||
positionDecimalPlaces?: number;
|
positionDecimalPlaces?: number;
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Order {
|
export interface Order {
|
||||||
status: string;
|
id?: string;
|
||||||
rejectionReason: string | null;
|
status?: string;
|
||||||
|
rejectionReason?: string | null;
|
||||||
size: string;
|
size: string;
|
||||||
price: string;
|
price: string;
|
||||||
market: Market | null;
|
market: Market | null;
|
||||||
type: string | null;
|
type: string | null;
|
||||||
side?: string;
|
side?: string;
|
||||||
|
timeInForce: OrderTimeInForce;
|
||||||
|
expiresAt?: Date | string | null;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
"@sentry/react": "^6.19.2",
|
"@sentry/react": "^6.19.2",
|
||||||
"@sentry/tracing": "^6.19.2",
|
"@sentry/tracing": "^6.19.2",
|
||||||
"@testing-library/user-event": "^14.2.1",
|
"@testing-library/user-event": "^14.2.1",
|
||||||
"@vegaprotocol/vegawallet-service-api-client": "0.4.14",
|
"@vegaprotocol/vegawallet-service-api-client": "0.4.15",
|
||||||
"@walletconnect/ethereum-provider": "^1.7.5",
|
"@walletconnect/ethereum-provider": "^1.7.5",
|
||||||
"@web3-react/core": "8.0.20-beta.0",
|
"@web3-react/core": "8.0.20-beta.0",
|
||||||
"@web3-react/metamask": "8.0.16-beta.0",
|
"@web3-react/metamask": "8.0.16-beta.0",
|
||||||
|
@ -6693,10 +6693,10 @@
|
|||||||
"@typescript-eslint/types" "5.22.0"
|
"@typescript-eslint/types" "5.22.0"
|
||||||
eslint-visitor-keys "^3.0.0"
|
eslint-visitor-keys "^3.0.0"
|
||||||
|
|
||||||
"@vegaprotocol/vegawallet-service-api-client@0.4.14":
|
"@vegaprotocol/vegawallet-service-api-client@^0.4.15":
|
||||||
version "0.4.14"
|
version "0.4.15"
|
||||||
resolved "https://registry.yarnpkg.com/@vegaprotocol/vegawallet-service-api-client/-/vegawallet-service-api-client-0.4.14.tgz#cdec296644380f95397688e10b753af328c38147"
|
resolved "https://registry.yarnpkg.com/@vegaprotocol/vegawallet-service-api-client/-/vegawallet-service-api-client-0.4.15.tgz#b303fec121b9b334a678161a6f66b360aeed5f0d"
|
||||||
integrity sha512-xQ/Dg4Bg+3LSHybYHV83i3G7i407Jj8ROElblZ2TTHTW9iHbBhbd/EHtWfUF2C6R6U27+JUZExnFPcZlvNXprA==
|
integrity sha512-YwJkUgFvFqpA1xPYQ30ILGddgzjwD9lclsu1GvwK2AUX/8e3iUcXyr37wLd/t8mDZ7P3Zb2AsuLJP8uZ6E1GHQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
es6-promise "^4.2.4"
|
es6-promise "^4.2.4"
|
||||||
url-parse "^1.4.3"
|
url-parse "^1.4.3"
|
||||||
|
Loading…
Reference in New Issue
Block a user