Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b2ec489d8 |
@@ -1,13 +1,13 @@
|
||||
import type { UseFormRegister } from 'react-hook-form';
|
||||
import { VegaWalletOrderType } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import { DealTicketMarketAmount } from './deal-ticket-market-amount';
|
||||
import { DealTicketLimitAmount } from './deal-ticket-limit-amount';
|
||||
import type { OrderSubmitInput } from '@vegaprotocol/orders';
|
||||
|
||||
export interface DealTicketAmountProps {
|
||||
orderType: VegaWalletOrderType;
|
||||
step: number;
|
||||
register: UseFormRegister<Order>;
|
||||
register: UseFormRegister<OrderSubmitInput>;
|
||||
quoteName: string;
|
||||
price?: string;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useState } from 'react';
|
||||
import type { VegaTxState } from '@vegaprotocol/wallet';
|
||||
import { VegaTransactionDialog, VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
import { DealTicket } from './deal-ticket';
|
||||
import type { DealTicketQuery_market } from './__generated__/DealTicketQuery';
|
||||
import type { OrderEvent_busEvents_event_Order } from '@vegaprotocol/orders';
|
||||
import { useOrderSubmit } from '@vegaprotocol/orders';
|
||||
import { OrderStatus } from '@vegaprotocol/types';
|
||||
import { OrderStatus, OrderType } from '@vegaprotocol/types';
|
||||
import { Icon, Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
|
||||
export interface DealTicketManagerProps {
|
||||
market: DealTicketQuery_market;
|
||||
@@ -17,26 +23,41 @@ export const DealTicketManager = ({
|
||||
}: DealTicketManagerProps) => {
|
||||
const [orderDialogOpen, setOrderDialogOpen] = useState(false);
|
||||
const { submit, transaction, finalizedOrder, reset } = useOrderSubmit(market);
|
||||
const getDialogTitle = (status?: string) => {
|
||||
switch (status) {
|
||||
case OrderStatus.Active:
|
||||
return 'Order submitted';
|
||||
case OrderStatus.Filled:
|
||||
return 'Order filled';
|
||||
case OrderStatus.PartiallyFilled:
|
||||
return 'Order partially filled';
|
||||
case OrderStatus.Parked:
|
||||
return 'Order parked';
|
||||
default:
|
||||
return 'Submission failed';
|
||||
|
||||
let title;
|
||||
let intent;
|
||||
let icon;
|
||||
let dialogContent;
|
||||
|
||||
if (finalizedOrder) {
|
||||
title = getDialogTitle(finalizedOrder);
|
||||
|
||||
if (finalizedOrder.status === OrderStatus.Rejected) {
|
||||
icon = <Icon name="cross" size={20} />;
|
||||
intent = Intent.Danger;
|
||||
dialogContent = (
|
||||
<p data-testid="error-reason">
|
||||
{t(`Reason: ${finalizedOrder.rejectionReason}`)}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
icon = <Icon name="tick" size={20} />;
|
||||
intent = Intent.Success;
|
||||
dialogContent = (
|
||||
<OrderSuccessContent order={finalizedOrder} transaction={transaction} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{children || (
|
||||
<DealTicket
|
||||
market={market}
|
||||
submit={submit}
|
||||
submit={(order) => {
|
||||
setOrderDialogOpen(true);
|
||||
submit(order);
|
||||
}}
|
||||
transactionStatus={
|
||||
transaction.status === VegaTxStatus.Requested ||
|
||||
transaction.status === VegaTxStatus.Pending
|
||||
@@ -45,15 +66,101 @@ export const DealTicketManager = ({
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
<VegaTransactionDialog
|
||||
key={`submit-order-dialog-${transaction.txHash}`}
|
||||
orderDialogOpen={orderDialogOpen}
|
||||
setOrderDialogOpen={setOrderDialogOpen}
|
||||
finalizedOrder={finalizedOrder}
|
||||
isOpen={orderDialogOpen}
|
||||
onChange={(isOpen) => {
|
||||
setOrderDialogOpen(isOpen);
|
||||
if (!isOpen) {
|
||||
reset();
|
||||
}
|
||||
}}
|
||||
transaction={transaction}
|
||||
reset={reset}
|
||||
title={getDialogTitle(finalizedOrder?.status)}
|
||||
/>
|
||||
intent={intent}
|
||||
title={title}
|
||||
icon={icon}
|
||||
>
|
||||
{dialogContent}
|
||||
</VegaTransactionDialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getDialogTitle = (finalizedOrder: OrderEvent_busEvents_event_Order) => {
|
||||
switch (finalizedOrder.status) {
|
||||
case OrderStatus.Active:
|
||||
return 'Order submitted';
|
||||
case OrderStatus.Filled:
|
||||
return 'Order filled';
|
||||
case OrderStatus.PartiallyFilled:
|
||||
return 'Order partially filled';
|
||||
case OrderStatus.Parked:
|
||||
return 'Order parked';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
interface OrderSuccessContentProps {
|
||||
order: OrderEvent_busEvents_event_Order;
|
||||
transaction: VegaTxState;
|
||||
}
|
||||
|
||||
const OrderSuccessContent = ({
|
||||
order,
|
||||
transaction,
|
||||
}: OrderSuccessContentProps) => {
|
||||
const headerClassName = 'text-h5 font-bold text-black dark:text-white';
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
return (
|
||||
<>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
{order.market && (
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Market`)}</p>
|
||||
<p>{t(`${order.market.name}`)}</p>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Status`)}</p>
|
||||
<p>{t(`${order.status}`)}</p>
|
||||
</div>
|
||||
{order.type === OrderType.Limit && order.market && (
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Price`)}</p>
|
||||
<p>
|
||||
{addDecimalsFormatNumber(order.price, order.market.decimalPlaces)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Amount`)}</p>
|
||||
<p
|
||||
className={
|
||||
order.side === 'Buy' ? 'text-vega-green' : 'text-vega-red'
|
||||
}
|
||||
>
|
||||
{`${order.side === 'Buy' ? '+' : '-'} ${order.size}
|
||||
`}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-8">
|
||||
{transaction.txHash && (
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Transaction`)}</p>
|
||||
<a
|
||||
className="underline break-words"
|
||||
data-testid="tx-block-explorer"
|
||||
href={`${VEGA_EXPLORER_URL}/txs/0x${transaction.txHash}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{transaction.txHash}
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -16,16 +16,16 @@ import { DealTicketAmount } from './deal-ticket-amount';
|
||||
import { TimeInForceSelector } from './time-in-force-selector';
|
||||
import type { DealTicketQuery_market } from './__generated__/DealTicketQuery';
|
||||
import { ExpirySelector } from './expiry-selector';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import type { OrderSubmitInput } from '@vegaprotocol/orders';
|
||||
import { getDefaultOrder, useOrderValidation } from '@vegaprotocol/orders';
|
||||
|
||||
export type TransactionStatus = 'default' | 'pending';
|
||||
|
||||
export interface DealTicketProps {
|
||||
market: DealTicketQuery_market;
|
||||
submit: (order: Order) => void;
|
||||
submit: (order: OrderSubmitInput) => void;
|
||||
transactionStatus: TransactionStatus;
|
||||
defaultOrder?: Order;
|
||||
defaultOrder?: OrderSubmitInput;
|
||||
}
|
||||
|
||||
export const DealTicket = ({
|
||||
@@ -39,7 +39,7 @@ export const DealTicket = ({
|
||||
handleSubmit,
|
||||
watch,
|
||||
formState: { errors },
|
||||
} = useForm<Order>({
|
||||
} = useForm<OrderSubmitInput>({
|
||||
mode: 'onChange',
|
||||
defaultValues: getDefaultOrder(market),
|
||||
});
|
||||
@@ -57,7 +57,7 @@ export const DealTicket = ({
|
||||
const isDisabled = transactionStatus === 'pending' || disabled;
|
||||
|
||||
const onSubmit = useCallback(
|
||||
(order: Order) => {
|
||||
(order: OrderSubmitInput) => {
|
||||
if (!isDisabled) {
|
||||
submit(order);
|
||||
}
|
||||
|
||||
@@ -6,25 +6,18 @@ import {
|
||||
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';
|
||||
import type { Orders_party_orders } from '../__generated__';
|
||||
|
||||
interface OrderEditDialogProps {
|
||||
title: string;
|
||||
order: Order | null;
|
||||
edit: (body: Order) => Promise<unknown>;
|
||||
order: Orders_party_orders;
|
||||
onSubmit: (order: Orders_party_orders) => void;
|
||||
}
|
||||
|
||||
interface FormFields {
|
||||
entryPrice: string;
|
||||
}
|
||||
|
||||
export const OrderEditDialog = ({
|
||||
order,
|
||||
title,
|
||||
edit,
|
||||
}: OrderEditDialogProps) => {
|
||||
export const OrderEditDialog = ({ order, onSubmit }: OrderEditDialogProps) => {
|
||||
const headerClassName = 'text-h5 font-bold text-black dark:text-white';
|
||||
const {
|
||||
register,
|
||||
@@ -39,7 +32,7 @@ export const OrderEditDialog = ({
|
||||
});
|
||||
if (!order) return null;
|
||||
return (
|
||||
<OrderDialogWrapper title={title} icon={<Icon name="hand-up" size={20} />}>
|
||||
<div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
{order.market && (
|
||||
<div>
|
||||
@@ -69,11 +62,10 @@ export const OrderEditDialog = ({
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 py-12">
|
||||
<form
|
||||
onSubmit={handleSubmit(async (data) => {
|
||||
await edit({
|
||||
onSubmit={handleSubmit((data) => {
|
||||
onSubmit({
|
||||
...order,
|
||||
price: data.entryPrice,
|
||||
});
|
||||
@@ -97,6 +89,6 @@ export const OrderEditDialog = ({
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
</OrderDialogWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Story, Meta } from '@storybook/react';
|
||||
import { OrderType, OrderStatus, OrderTimeInForce } from '@vegaprotocol/types';
|
||||
import { OrderList, OrderListTable } from './order-list';
|
||||
import { useState } from 'react';
|
||||
import type { Order, VegaTxState } from '@vegaprotocol/wallet';
|
||||
import type { VegaTxState } from '@vegaprotocol/wallet';
|
||||
import { VegaTransactionDialog, VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
import { generateOrdersArray } from '../mocks';
|
||||
|
||||
@@ -18,9 +17,6 @@ const Template: Story = (args) => {
|
||||
<OrderListTable
|
||||
rowData={args.data}
|
||||
cancel={cancel}
|
||||
setEditOrderDialogOpen={() => {
|
||||
return;
|
||||
}}
|
||||
setEditOrder={() => {
|
||||
return;
|
||||
}}
|
||||
@@ -41,36 +37,22 @@ const Template2: Story = (args) => {
|
||||
txHash: null,
|
||||
signature: null,
|
||||
};
|
||||
const finalizedOrder: Order = {
|
||||
status: OrderStatus.Cancelled,
|
||||
rejectionReason: null,
|
||||
size: '10',
|
||||
price: '1000',
|
||||
market: { name: 'ETH/DAI (30 Jun 2022)', decimalPlaces: 5 },
|
||||
type: OrderType.Limit,
|
||||
timeInForce: OrderTimeInForce.GTC,
|
||||
};
|
||||
const reset = () => null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ height: 1000 }}>
|
||||
<OrderListTable
|
||||
rowData={args.data}
|
||||
cancel={cancel}
|
||||
setEditOrderDialogOpen={() => {
|
||||
return;
|
||||
}}
|
||||
setEditOrder={() => {
|
||||
return;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<VegaTransactionDialog
|
||||
orderDialogOpen={open}
|
||||
setOrderDialogOpen={setOpen}
|
||||
finalizedOrder={finalizedOrder}
|
||||
isOpen={open}
|
||||
onChange={setOpen}
|
||||
transaction={transaction}
|
||||
reset={reset}
|
||||
title={'Order cancelled'}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -5,99 +5,98 @@ import {
|
||||
getDateTimeFormat,
|
||||
t,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { AgGridDynamic as AgGrid, Button } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
AgGridDynamic as AgGrid,
|
||||
Button,
|
||||
Dialog,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import type {
|
||||
ICellRendererParams,
|
||||
ValueFormatterParams,
|
||||
} from 'ag-grid-community';
|
||||
import type {
|
||||
AgGridReact,
|
||||
AgGridReactProps,
|
||||
AgReactUiProps,
|
||||
} from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { AgGridColumn } from 'ag-grid-react';
|
||||
import { forwardRef, useState } from 'react';
|
||||
import type { Orders_party_ordersConnection_edges_node } from '../';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
import type { OrderCancelInput } from '../../order-hooks/use-order-cancel';
|
||||
import { useOrderCancel } from '../../order-hooks/use-order-cancel';
|
||||
import { VegaTransactionDialog } from '@vegaprotocol/wallet';
|
||||
import { useOrderEdit } from '../../order-hooks/use-order-edit';
|
||||
import { OrderEditDialog } from './order-edit-dialog';
|
||||
|
||||
type OrderListProps = AgGridReactProps | AgReactUiProps;
|
||||
interface OrderListProps {
|
||||
data: Orders_party_ordersConnection_edges_node[] | null;
|
||||
}
|
||||
|
||||
export const OrderList = forwardRef<AgGridReact, OrderListProps>(
|
||||
(props, ref) => {
|
||||
({ data }, ref) => {
|
||||
// Cancel transaction dialog
|
||||
const [cancelOrderDialogOpen, setCancelOrderDialogOpen] = useState(false);
|
||||
// Edit order transaction dialog
|
||||
const [editOrderDialogOpen, setEditOrderDialogOpen] = useState(false);
|
||||
// Order for edit order dialog
|
||||
const [editOrder, setEditOrder] =
|
||||
useState<Orders_party_ordersConnection_edges_node | null>(null);
|
||||
|
||||
const { transaction, updatedOrder, reset, cancel } = useOrderCancel();
|
||||
const { transaction, reset, cancel } = useOrderCancel();
|
||||
const {
|
||||
transaction: editTransaction,
|
||||
updatedOrder: editedOrder,
|
||||
reset: resetEdit,
|
||||
edit,
|
||||
} = useOrderEdit();
|
||||
const getCancelDialogTitle = (status?: string) => {
|
||||
switch (status) {
|
||||
case OrderStatus.Cancelled:
|
||||
return 'Order cancelled';
|
||||
case OrderStatus.Rejected:
|
||||
return 'Order rejected';
|
||||
case OrderStatus.Expired:
|
||||
return 'Order expired';
|
||||
default:
|
||||
return 'Cancellation failed';
|
||||
}
|
||||
};
|
||||
const getEditDialogTitle = () =>
|
||||
editedOrder
|
||||
? t(
|
||||
`Order ${
|
||||
editOrder?.market?.tradableInstrument.instrument.code ?? ''
|
||||
} updated`
|
||||
)
|
||||
: t(
|
||||
`Edit ${
|
||||
editOrder?.market?.tradableInstrument.instrument.code ?? ''
|
||||
} order`
|
||||
);
|
||||
// const getEditDialogTitle = () =>
|
||||
// editedOrder
|
||||
// ? t(
|
||||
// `Order ${
|
||||
// editOrder?.market?.tradableInstrument.instrument.code ?? ''
|
||||
// } updated`
|
||||
// )
|
||||
// : t(
|
||||
// `Edit ${
|
||||
// editOrder?.market?.tradableInstrument.instrument.code ?? ''
|
||||
// } order`
|
||||
// );
|
||||
return (
|
||||
<>
|
||||
<OrderListTable
|
||||
{...props}
|
||||
cancel={cancel}
|
||||
data={data}
|
||||
cancel={(order) => {
|
||||
setCancelOrderDialogOpen(true);
|
||||
cancel(order);
|
||||
}}
|
||||
ref={ref}
|
||||
setEditOrderDialogOpen={setEditOrderDialogOpen}
|
||||
setEditOrder={setEditOrder}
|
||||
/>
|
||||
<VegaTransactionDialog
|
||||
key={`cancel-order-dialog-${transaction.txHash}`}
|
||||
orderDialogOpen={cancelOrderDialogOpen}
|
||||
setOrderDialogOpen={setCancelOrderDialogOpen}
|
||||
isOpen={cancelOrderDialogOpen}
|
||||
onChange={(isOpen) => {
|
||||
setCancelOrderDialogOpen(isOpen);
|
||||
if (!isOpen) {
|
||||
reset();
|
||||
}
|
||||
}}
|
||||
transaction={transaction}
|
||||
reset={reset}
|
||||
title={getCancelDialogTitle(updatedOrder?.status)}
|
||||
finalizedOrder={updatedOrder}
|
||||
/>
|
||||
<VegaTransactionDialog
|
||||
key={`edit-order-dialog-${transaction.txHash}`}
|
||||
orderDialogOpen={editOrderDialogOpen}
|
||||
setOrderDialogOpen={setEditOrderDialogOpen}
|
||||
isOpen={editOrderDialogOpen}
|
||||
onChange={(isOpen) => {
|
||||
setEditOrderDialogOpen(isOpen);
|
||||
if (!isOpen) {
|
||||
resetEdit();
|
||||
}
|
||||
}}
|
||||
transaction={editTransaction}
|
||||
reset={resetEdit}
|
||||
title={getEditDialogTitle()}
|
||||
finalizedOrder={editedOrder}
|
||||
>
|
||||
<OrderEditDialog
|
||||
title={getEditDialogTitle()}
|
||||
order={editOrder}
|
||||
edit={edit}
|
||||
/>
|
||||
</VegaTransactionDialog>
|
||||
/>
|
||||
<EditOrderDialog
|
||||
editOrder={editOrder}
|
||||
setEditOrder={setEditOrder}
|
||||
onSubmit={(order) => {
|
||||
setEditOrder(null);
|
||||
setEditOrderDialogOpen(true);
|
||||
// @ts-ignore fix me, market is null
|
||||
edit(order);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -109,17 +108,16 @@ type OrderListTableValueFormatterParams = Omit<
|
||||
> & {
|
||||
data: Orders_party_ordersConnection_edges_node | null;
|
||||
};
|
||||
|
||||
type OrderListTableProps = (AgGridReactProps | AgReactUiProps) & {
|
||||
cancel: (body?: unknown) => Promise<unknown>;
|
||||
setEditOrderDialogOpen: (value: boolean) => void;
|
||||
interface OrderListTableProps {
|
||||
data: Orders_party_ordersConnection_edges_node[] | null;
|
||||
cancel: (order: OrderCancelInput) => void;
|
||||
setEditOrder: (
|
||||
order: Orders_party_ordersConnection_edges_node | null
|
||||
) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
||||
({ cancel, setEditOrderDialogOpen, setEditOrder, ...props }, ref) => {
|
||||
({ data, cancel, setEditOrder }, ref) => {
|
||||
return (
|
||||
<AgGrid
|
||||
ref={ref}
|
||||
@@ -128,7 +126,6 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
getRowId={({ data }) => data.id}
|
||||
rowHeight={40}
|
||||
{...props}
|
||||
>
|
||||
<AgGridColumn
|
||||
headerName={t('Market')}
|
||||
@@ -274,7 +271,6 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
||||
data-testid="edit"
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
setEditOrderDialogOpen(true);
|
||||
setEditOrder(data);
|
||||
}}
|
||||
>
|
||||
@@ -301,7 +297,10 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
||||
<Button
|
||||
data-testid="cancel"
|
||||
onClick={async () => {
|
||||
await cancel(data);
|
||||
await cancel({
|
||||
orderId: data.id,
|
||||
marketId: data.market.id,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
@@ -315,3 +314,23 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
interface EditOrderDialogProps {
|
||||
editOrder: Orders_party_ordersConnection_edges_node | null;
|
||||
setEditOrder: (
|
||||
order: Orders_party_ordersConnection_edges_node | null
|
||||
) => void;
|
||||
onSubmit: (order: Orders_party_ordersConnection_edges_node) => void;
|
||||
}
|
||||
|
||||
const EditOrderDialog = ({
|
||||
editOrder,
|
||||
setEditOrder,
|
||||
onSubmit,
|
||||
}: EditOrderDialogProps) => {
|
||||
return (
|
||||
<Dialog open={Boolean(editOrder)} onChange={() => setEditOrder(null)}>
|
||||
{editOrder && <OrderEditDialog order={editOrder} onSubmit={onSubmit} />}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export * from './components';
|
||||
export * from './order-hooks';
|
||||
export * from './utils';
|
||||
export * from './market';
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import type { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||
|
||||
export interface Market {
|
||||
__typename?: string;
|
||||
id: string;
|
||||
positionDecimalPlaces: number;
|
||||
state: MarketState;
|
||||
decimalPlaces: number;
|
||||
tradingMode: MarketTradingMode;
|
||||
tradableInstrument?: any;
|
||||
depth?: any;
|
||||
}
|
||||
@@ -8,13 +8,22 @@ import type {
|
||||
} from './__generated__/OrderEvent';
|
||||
import { ORDER_EVENT_SUB } from './order-event-query';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { OrderStatus } from '@vegaprotocol/types';
|
||||
import { determineId } from '@vegaprotocol/react-helpers';
|
||||
import type { Subscription } from 'zen-observable-ts';
|
||||
|
||||
export type OrderCancelInput = {
|
||||
orderId: string;
|
||||
marketId: string;
|
||||
};
|
||||
|
||||
export const useOrderCancel = () => {
|
||||
const { keypair } = useVegaWallet();
|
||||
const { send, transaction, reset: resetTransaction } = useVegaTransaction();
|
||||
const {
|
||||
send,
|
||||
transaction,
|
||||
setComplete,
|
||||
reset: resetTransaction,
|
||||
} = useVegaTransaction();
|
||||
const [updatedOrder, setUpdatedOrder] =
|
||||
useState<OrderEvent_busEvents_event_Order | null>(null);
|
||||
const client = useApolloClient();
|
||||
@@ -35,23 +44,11 @@ export const useOrderCancel = () => {
|
||||
}, [resetTransaction]);
|
||||
|
||||
const cancel = useCallback(
|
||||
async (order) => {
|
||||
async (order: OrderCancelInput) => {
|
||||
if (!keypair) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
OrderStatus.Cancelled,
|
||||
OrderStatus.Rejected,
|
||||
OrderStatus.Expired,
|
||||
OrderStatus.Filled,
|
||||
OrderStatus.Stopped,
|
||||
].includes(order.status)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setUpdatedOrder(null);
|
||||
|
||||
try {
|
||||
@@ -59,13 +56,13 @@ export const useOrderCancel = () => {
|
||||
pubKey: keypair.pub,
|
||||
propagate: true,
|
||||
orderCancellation: {
|
||||
orderId: order.id,
|
||||
marketId: order.market.id,
|
||||
orderId: order.orderId,
|
||||
marketId: order.marketId,
|
||||
},
|
||||
});
|
||||
|
||||
if (res?.signature) {
|
||||
const resId = order.id ?? determineId(res.signature);
|
||||
const resId = order.orderId ?? determineId(res.signature);
|
||||
setUpdatedOrder(null);
|
||||
|
||||
if (resId) {
|
||||
@@ -94,18 +91,18 @@ export const useOrderCancel = () => {
|
||||
matchingOrderEvent.event.__typename === 'Order'
|
||||
) {
|
||||
setUpdatedOrder(matchingOrderEvent.event);
|
||||
setComplete();
|
||||
subRef.current?.unsubscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
Sentry.captureException(e);
|
||||
return;
|
||||
}
|
||||
},
|
||||
[client, keypair, send]
|
||||
[client, keypair, send, setComplete]
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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';
|
||||
@@ -12,10 +11,27 @@ import type {
|
||||
OrderEventVariables,
|
||||
} from './__generated__';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import type { OrderTimeInForce } from '@vegaprotocol/types';
|
||||
|
||||
type OrderEditInput = {
|
||||
id: string;
|
||||
market: {
|
||||
id: string;
|
||||
decimalPlaces: number;
|
||||
};
|
||||
price: string;
|
||||
timeInForce: OrderTimeInForce;
|
||||
expiresAt?: string;
|
||||
};
|
||||
|
||||
export const useOrderEdit = () => {
|
||||
const { keypair } = useVegaWallet();
|
||||
const { send, transaction, reset: resetTransaction } = useVegaTransaction();
|
||||
const {
|
||||
send,
|
||||
transaction,
|
||||
setComplete,
|
||||
reset: resetTransaction,
|
||||
} = useVegaTransaction();
|
||||
const [updatedOrder, setUpdatedOrder] =
|
||||
useState<OrderEvent_busEvents_event_Order | null>(null);
|
||||
const client = useApolloClient();
|
||||
@@ -36,8 +52,8 @@ export const useOrderEdit = () => {
|
||||
}, [resetTransaction]);
|
||||
|
||||
const edit = useCallback(
|
||||
async (order: Order) => {
|
||||
if (!keypair || !order.market || !order.market.id) {
|
||||
async (order: OrderEditInput) => {
|
||||
if (!keypair) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,7 +67,7 @@ export const useOrderEdit = () => {
|
||||
orderId: order.id,
|
||||
marketId: order.market.id,
|
||||
price: {
|
||||
value: removeDecimal(order.price, order.market?.decimalPlaces),
|
||||
value: removeDecimal(order.price, order.market.decimalPlaces),
|
||||
},
|
||||
timeInForce: VegaWalletOrderTimeInForce[order.timeInForce],
|
||||
sizeDelta: 0,
|
||||
@@ -96,18 +112,18 @@ export const useOrderEdit = () => {
|
||||
matchingOrderEvent.event.__typename === 'Order'
|
||||
) {
|
||||
setUpdatedOrder(matchingOrderEvent.event);
|
||||
setComplete();
|
||||
subRef.current?.unsubscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
Sentry.captureException(e);
|
||||
return;
|
||||
}
|
||||
},
|
||||
[client, keypair, send]
|
||||
[client, keypair, setComplete, send]
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,22 +1,44 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import type { Order } from '../utils/get-default-order';
|
||||
import { ORDER_EVENT_SUB } from './order-event-query';
|
||||
import type {
|
||||
OrderEvent,
|
||||
OrderEventVariables,
|
||||
OrderEvent_busEvents_event_Order,
|
||||
} from './__generated__';
|
||||
import type {
|
||||
VegaWalletOrderTimeInForce,
|
||||
VegaWalletOrderSide,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { VegaWalletOrderType, useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { determineId, removeDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { useVegaTransaction } from '@vegaprotocol/wallet';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import type { Market } from '../market';
|
||||
import type { Subscription } from 'zen-observable-ts';
|
||||
|
||||
export const useOrderSubmit = (market: Market) => {
|
||||
export type OrderSubmitInput = {
|
||||
size: string;
|
||||
type: VegaWalletOrderType.Market | VegaWalletOrderType.Limit;
|
||||
timeInForce: VegaWalletOrderTimeInForce;
|
||||
side: VegaWalletOrderSide;
|
||||
price?: string;
|
||||
expiration?: Date;
|
||||
};
|
||||
|
||||
export type OrderSubmitMarket = {
|
||||
id: string;
|
||||
decimalPlaces: number;
|
||||
positionDecimalPlaces: number;
|
||||
};
|
||||
|
||||
export const useOrderSubmit = (market: OrderSubmitMarket) => {
|
||||
const { keypair } = useVegaWallet();
|
||||
const { send, transaction, reset: resetTransaction } = useVegaTransaction();
|
||||
const {
|
||||
send,
|
||||
transaction,
|
||||
setComplete,
|
||||
reset: resetTransaction,
|
||||
} = useVegaTransaction();
|
||||
const [finalizedOrder, setFinalizedOrder] =
|
||||
useState<OrderEvent_busEvents_event_Order | null>(null);
|
||||
const client = useApolloClient();
|
||||
@@ -37,12 +59,13 @@ export const useOrderSubmit = (market: Market) => {
|
||||
}, [resetTransaction]);
|
||||
|
||||
const submit = useCallback(
|
||||
async (order: Order) => {
|
||||
if (!keypair || !order.side) {
|
||||
async (order: OrderSubmitInput) => {
|
||||
if (!keypair) {
|
||||
return;
|
||||
}
|
||||
|
||||
setFinalizedOrder(null);
|
||||
|
||||
try {
|
||||
const res = await send({
|
||||
pubKey: keypair.pub,
|
||||
@@ -57,11 +80,12 @@ export const useOrderSubmit = (market: Market) => {
|
||||
type: order.type,
|
||||
side: order.side,
|
||||
timeInForce: order.timeInForce,
|
||||
expiresAt: order.expiration
|
||||
? // Wallet expects timestamp in nanoseconds, we don't have that level of accuracy so
|
||||
// just append 6 zeroes
|
||||
order.expiration.getTime().toString() + '000000'
|
||||
: undefined,
|
||||
expiresAt:
|
||||
order.type === VegaWalletOrderType.Limit && order.expiration
|
||||
? // Wallet expects timestamp in nanoseconds, we don't have that level of accuracy so
|
||||
// just append 6 zeroes
|
||||
order.expiration.getTime().toString() + '000000'
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -93,6 +117,7 @@ export const useOrderSubmit = (market: Market) => {
|
||||
matchingOrderEvent.event.__typename === 'Order'
|
||||
) {
|
||||
setFinalizedOrder(matchingOrderEvent.event);
|
||||
setComplete();
|
||||
subRef.current?.unsubscribe();
|
||||
}
|
||||
});
|
||||
@@ -104,14 +129,7 @@ export const useOrderSubmit = (market: Market) => {
|
||||
return;
|
||||
}
|
||||
},
|
||||
[
|
||||
client,
|
||||
keypair,
|
||||
send,
|
||||
market.id,
|
||||
market.decimalPlaces,
|
||||
market.positionDecimalPlaces,
|
||||
]
|
||||
[client, keypair, send, market, setComplete]
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
import type { FieldErrors } from 'react-hook-form';
|
||||
import { useMemo } from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { Order } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
useVegaWallet,
|
||||
VegaWalletOrderTimeInForce as OrderTimeInForce,
|
||||
VegaWalletOrderType as OrderType,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||
import type { Market } from '../market';
|
||||
import { ERROR_SIZE_DECIMAL } from '../utils/validate-size';
|
||||
import type { OrderSubmitInput } from './use-order-submit';
|
||||
|
||||
export type ValidationProps = {
|
||||
export type UseValidationArgs = {
|
||||
step: number;
|
||||
market: Market;
|
||||
market: {
|
||||
id: string;
|
||||
decimalPlaces: number;
|
||||
positionDecimalPlaces: number;
|
||||
state: MarketState;
|
||||
tradingMode: MarketTradingMode;
|
||||
};
|
||||
orderType: OrderType;
|
||||
orderTimeInForce: OrderTimeInForce;
|
||||
fieldErrors?: FieldErrors<Order>;
|
||||
fieldErrors?: FieldErrors<OrderSubmitInput>;
|
||||
};
|
||||
|
||||
export const marketTranslations = (marketState: MarketState) => {
|
||||
@@ -34,7 +39,7 @@ export const useOrderValidation = ({
|
||||
fieldErrors = {},
|
||||
orderType,
|
||||
orderTimeInForce,
|
||||
}: ValidationProps) => {
|
||||
}: UseValidationArgs) => {
|
||||
const { keypair } = useVegaWallet();
|
||||
|
||||
const { message, isDisabled } = useMemo(() => {
|
||||
|
||||
@@ -4,38 +4,13 @@ import {
|
||||
VegaWalletOrderSide,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { toDecimal } from '@vegaprotocol/react-helpers';
|
||||
import type { Market } from '../market';
|
||||
import type { OrderStatus } from '@vegaprotocol/types';
|
||||
import type { OrderSubmitInput, OrderSubmitMarket } from '../order-hooks';
|
||||
|
||||
export type Order =
|
||||
| {
|
||||
size: string;
|
||||
type: VegaWalletOrderType.Market;
|
||||
timeInForce: VegaWalletOrderTimeInForce;
|
||||
side: VegaWalletOrderSide;
|
||||
price?: never;
|
||||
expiration?: never;
|
||||
rejectionReason: string | null;
|
||||
status?: OrderStatus;
|
||||
market?: Market | null;
|
||||
}
|
||||
| {
|
||||
size: string;
|
||||
type: VegaWalletOrderType.Limit;
|
||||
timeInForce: VegaWalletOrderTimeInForce;
|
||||
side: VegaWalletOrderSide;
|
||||
price?: string;
|
||||
expiration?: Date;
|
||||
rejectionReason: string | null;
|
||||
status?: OrderStatus;
|
||||
market?: Market | null;
|
||||
};
|
||||
|
||||
export const getDefaultOrder = (market: Market): Order => ({
|
||||
export const getDefaultOrder = (
|
||||
market: OrderSubmitMarket
|
||||
): OrderSubmitInput => ({
|
||||
type: VegaWalletOrderType.Market,
|
||||
side: VegaWalletOrderSide.Buy,
|
||||
timeInForce: VegaWalletOrderTimeInForce.IOC,
|
||||
size: String(toDecimal(market.positionDecimalPlaces)),
|
||||
rejectionReason: null,
|
||||
market: null,
|
||||
});
|
||||
|
||||
@@ -8,8 +8,7 @@ export enum VegaTxStatus {
|
||||
Requested = 'Requested',
|
||||
Pending = 'Pending',
|
||||
Error = 'Error',
|
||||
// Note no complete state as we have to use api calls/subs to check if
|
||||
// our transaction was completed
|
||||
Complete = 'Complete',
|
||||
}
|
||||
|
||||
export interface VegaTxState {
|
||||
@@ -48,6 +47,10 @@ export const useVegaTransaction = () => {
|
||||
setTransaction(initialState);
|
||||
}, [setTransaction]);
|
||||
|
||||
const setComplete = useCallback(() => {
|
||||
setTransaction({ status: VegaTxStatus.Complete });
|
||||
}, [setTransaction]);
|
||||
|
||||
const send = useCallback(
|
||||
async (tx: TransactionSubmission) => {
|
||||
setTransaction({
|
||||
@@ -91,5 +94,5 @@ export const useVegaTransaction = () => {
|
||||
[sendTx, handleError, setTransaction, reset]
|
||||
);
|
||||
|
||||
return { send, transaction, reset };
|
||||
return { send, transaction, setComplete, reset };
|
||||
};
|
||||
|
||||
@@ -1,155 +1,95 @@
|
||||
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import { useEffect } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { Dialog, Icon, Intent, Loader } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { VegaTxState } from '../use-vega-transaction';
|
||||
import { VegaTxStatus } from '../use-vega-transaction';
|
||||
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ReactNode } from 'react';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
formatLabel,
|
||||
t,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { OrderType } from '@vegaprotocol/types';
|
||||
import type { Order } from '../wallet-types';
|
||||
import get from 'lodash/get';
|
||||
|
||||
export interface VegaTransactionDialogProps {
|
||||
orderDialogOpen: boolean;
|
||||
setOrderDialogOpen: (isOpen: boolean) => void;
|
||||
finalizedOrder: Order | null;
|
||||
isOpen: boolean;
|
||||
onChange: (isOpen: boolean) => void;
|
||||
transaction: VegaTxState;
|
||||
reset: () => void;
|
||||
title?: string;
|
||||
intent?: Intent;
|
||||
icon?: ReactNode;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
const getDialogIntent = (
|
||||
finalizedOrder: Order | null,
|
||||
transaction: VegaTxState
|
||||
) => {
|
||||
if (finalizedOrder) {
|
||||
return !finalizedOrder.rejectionReason ? Intent.Success : Intent.Danger;
|
||||
}
|
||||
switch (transaction.status) {
|
||||
case VegaTxStatus.Requested:
|
||||
return Intent.Warning;
|
||||
case VegaTxStatus.Pending:
|
||||
return Intent.Warning;
|
||||
case VegaTxStatus.Error:
|
||||
return Intent.Danger;
|
||||
default:
|
||||
return Intent.None;
|
||||
}
|
||||
};
|
||||
|
||||
export const VegaTransactionDialog = ({
|
||||
orderDialogOpen,
|
||||
setOrderDialogOpen,
|
||||
finalizedOrder,
|
||||
isOpen,
|
||||
onChange,
|
||||
transaction,
|
||||
reset,
|
||||
title = '',
|
||||
title,
|
||||
intent,
|
||||
icon,
|
||||
children,
|
||||
}: VegaTransactionDialogProps) => {
|
||||
// open / close dialog
|
||||
useEffect(() => {
|
||||
if (transaction.status !== VegaTxStatus.Default || finalizedOrder) {
|
||||
setOrderDialogOpen(true);
|
||||
} else {
|
||||
setOrderDialogOpen(false);
|
||||
}
|
||||
}, [finalizedOrder, setOrderDialogOpen, transaction.status]);
|
||||
|
||||
const defaultProps = useDefaultProps(transaction);
|
||||
return (
|
||||
<Dialog
|
||||
open={orderDialogOpen}
|
||||
onChange={(isOpen) => {
|
||||
setOrderDialogOpen(isOpen);
|
||||
|
||||
// If closing reset
|
||||
if (!isOpen) {
|
||||
reset();
|
||||
}
|
||||
}}
|
||||
intent={getDialogIntent(finalizedOrder, transaction)}
|
||||
open={isOpen}
|
||||
onChange={onChange}
|
||||
intent={intent || defaultProps.intent}
|
||||
>
|
||||
<VegaDialog
|
||||
key={`${title.toLowerCase().split(' ').join('-')}-tx-${
|
||||
transaction.txHash
|
||||
}`}
|
||||
transaction={transaction}
|
||||
finalizedOrder={finalizedOrder}
|
||||
title={title}
|
||||
children={children}
|
||||
/>
|
||||
<DialogWrapper
|
||||
title={title || defaultProps.title}
|
||||
icon={icon || defaultProps.icon}
|
||||
>
|
||||
{children || defaultProps.content}
|
||||
</DialogWrapper>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
interface VegaDialogProps {
|
||||
transaction: VegaTxState;
|
||||
finalizedOrder: Order | null;
|
||||
interface DialogWrapperProps {
|
||||
children: ReactNode;
|
||||
icon: ReactNode;
|
||||
title: string;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const VegaDialog = ({
|
||||
transaction,
|
||||
finalizedOrder,
|
||||
title,
|
||||
export const DialogWrapper = ({
|
||||
children,
|
||||
}: VegaDialogProps) => {
|
||||
icon,
|
||||
title,
|
||||
}: DialogWrapperProps) => {
|
||||
return (
|
||||
<div className="flex gap-12 max-w-full text-ui">
|
||||
<div className="pt-8 fill-current">{icon}</div>
|
||||
<div className="flex-1">
|
||||
<h1 className="text-h4 text-black dark:text-white capitalize mb-12">
|
||||
{title}
|
||||
</h1>
|
||||
<div className="text-black-40 dark:text-white-40">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const useDefaultProps = (transaction: VegaTxState) => {
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const headerClassName = 'text-h5 font-bold text-black dark:text-white';
|
||||
|
||||
if (children && transaction.status === VegaTxStatus.Default) {
|
||||
return <div>{children}</div>;
|
||||
}
|
||||
|
||||
// Rejected by wallet
|
||||
if (transaction.status === VegaTxStatus.Requested) {
|
||||
return (
|
||||
<OrderDialogWrapper
|
||||
title="Confirm transaction in wallet"
|
||||
icon={<Icon name="hand-up" size={20} />}
|
||||
>
|
||||
<p>
|
||||
{t(
|
||||
'Please open your wallet application and confirm or reject the transaction'
|
||||
)}
|
||||
</p>
|
||||
</OrderDialogWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
// Transaction error
|
||||
if (transaction.status === VegaTxStatus.Error) {
|
||||
return (
|
||||
<OrderDialogWrapper
|
||||
title="Order rejected by wallet"
|
||||
icon={<Icon name="warning-sign" size={20} />}
|
||||
>
|
||||
{transaction.error && (
|
||||
<pre className="text-ui break-all whitespace-pre-wrap">
|
||||
{get(transaction.error, 'error') ??
|
||||
JSON.stringify(transaction.error, null, 2)}
|
||||
</pre>
|
||||
)}
|
||||
</OrderDialogWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
// Pending consensus
|
||||
if (!finalizedOrder) {
|
||||
return (
|
||||
<OrderDialogWrapper
|
||||
title="Awaiting network confirmation"
|
||||
icon={<Loader size="small" />}
|
||||
>
|
||||
{transaction.txHash && (
|
||||
switch (transaction.status) {
|
||||
case VegaTxStatus.Requested:
|
||||
return {
|
||||
title: 'Confirm transaction in Vega wallet',
|
||||
intent: Intent.Warning,
|
||||
icon: <Icon name="hand-up" size={20} />,
|
||||
content: (
|
||||
<p>
|
||||
{t(
|
||||
'Please open your wallet application and confirm or reject the transaction'
|
||||
)}
|
||||
</p>
|
||||
),
|
||||
};
|
||||
case VegaTxStatus.Pending:
|
||||
return {
|
||||
title: 'Awaiting transaction',
|
||||
intent: Intent.None,
|
||||
icon: <Loader size="small" />,
|
||||
content: (
|
||||
<p className="break-all">
|
||||
{t('Waiting for few more blocks')} -
|
||||
{t('Waiting for confirmation')} -{' '}
|
||||
<a
|
||||
className="underline"
|
||||
data-testid="tx-block-explorer"
|
||||
@@ -160,107 +100,46 @@ export const VegaDialog = ({
|
||||
{t('View in block explorer')}
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
</OrderDialogWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
// Order on network but was rejected
|
||||
if (finalizedOrder.status === 'Rejected') {
|
||||
return (
|
||||
<OrderDialogWrapper
|
||||
title="Order failed"
|
||||
icon={<Icon name="warning-sign" size={20} />}
|
||||
>
|
||||
<p data-testid="error-reason">
|
||||
{finalizedOrder.rejectionReason &&
|
||||
t(`Reason: ${formatLabel(finalizedOrder.rejectionReason)}`)}
|
||||
</p>
|
||||
</OrderDialogWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<OrderDialogWrapper title={title} icon={<Icon name="tick" size={20} />}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
{finalizedOrder.market && (
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Market`)}</p>
|
||||
<p>{t(`${finalizedOrder.market.name}`)}</p>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Status`)}</p>
|
||||
<p>{t(`${finalizedOrder.status}`)}</p>
|
||||
</div>
|
||||
{finalizedOrder.type === OrderType.Limit && finalizedOrder.market && (
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Price`)}</p>
|
||||
<p>
|
||||
{addDecimalsFormatNumber(
|
||||
finalizedOrder.price,
|
||||
finalizedOrder.market.decimalPlaces
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Amount`)}</p>
|
||||
<p
|
||||
className={
|
||||
finalizedOrder.side === 'Buy'
|
||||
? 'text-vega-green'
|
||||
: 'text-vega-red'
|
||||
}
|
||||
>
|
||||
{`${finalizedOrder.side === 'Buy' ? '+' : '-'} ${
|
||||
finalizedOrder.size
|
||||
}
|
||||
`}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-8">
|
||||
{transaction.txHash && (
|
||||
<div>
|
||||
<p className={headerClassName}>{t(`Transaction`)}</p>
|
||||
),
|
||||
};
|
||||
case VegaTxStatus.Error:
|
||||
return {
|
||||
title: 'Transaction rejected by wallet',
|
||||
icon: <Icon name="warning-sign" size={20} />,
|
||||
intent: Intent.Danger,
|
||||
content: (
|
||||
<pre className="text-ui break-all whitespace-pre-wrap">
|
||||
{get(transaction.error, 'error') ??
|
||||
JSON.stringify(transaction.error, null, 2)}
|
||||
</pre>
|
||||
),
|
||||
};
|
||||
case VegaTxStatus.Complete:
|
||||
return {
|
||||
title: 'Transaction complete',
|
||||
icon: <Icon name="tick" size={20} />,
|
||||
intent: Intent.Success,
|
||||
content: (
|
||||
<p className="break-all">
|
||||
{t('Transaction seen on chain')} -{' '}
|
||||
<a
|
||||
className="underline break-words"
|
||||
className="underline"
|
||||
data-testid="tx-block-explorer"
|
||||
href={`${VEGA_EXPLORER_URL}/txs/0x${transaction.txHash}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{transaction.txHash}
|
||||
{t('View in block explorer')}
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</OrderDialogWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
interface OrderDialogWrapperProps {
|
||||
children: ReactNode;
|
||||
icon: ReactNode;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export const OrderDialogWrapper = ({
|
||||
children,
|
||||
icon,
|
||||
title,
|
||||
}: OrderDialogWrapperProps) => {
|
||||
const headerClassName = 'text-h4 font-bold text-black dark:text-white';
|
||||
return (
|
||||
<div className="flex gap-12 max-w-full">
|
||||
<div className="pt-8 fill-current">{icon}</div>
|
||||
<div data-testid="order-wrapper" className="flex-1">
|
||||
<h1 data-testid="order-status-header" className={headerClassName}>
|
||||
{title}
|
||||
</h1>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
</p>
|
||||
),
|
||||
};
|
||||
default:
|
||||
return {
|
||||
title: '',
|
||||
icon: null,
|
||||
intent: undefined,
|
||||
content: null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,16 +44,3 @@ export interface Market {
|
||||
decimalPlaces: number;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export interface Order {
|
||||
id?: string;
|
||||
status?: string;
|
||||
rejectionReason?: string | null;
|
||||
size: string;
|
||||
price: string;
|
||||
market: Market | null;
|
||||
type: string | null;
|
||||
side?: string;
|
||||
timeInForce: OrderTimeInForce;
|
||||
expiresAt?: Date | string | null;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,12 @@ const getProps = (
|
||||
intent: Intent.None,
|
||||
children: <Step>Awaiting transaction</Step>,
|
||||
},
|
||||
[VegaTxStatus.Complete]: {
|
||||
title: t('Withdrawal successful'),
|
||||
icon: 'tick',
|
||||
intent: Intent.Success,
|
||||
children: <Step>Withdrawal has completed</Step>,
|
||||
},
|
||||
};
|
||||
|
||||
const ethTxPropsMap: Record<EthTxStatus, DialogProps> = {
|
||||
|
||||
Reference in New Issue
Block a user