2022-03-30 09:49:48 +00:00
|
|
|
import type { OrderSide } from '@vegaprotocol/wallet';
|
|
|
|
import { OrderTimeInForce, OrderType } from '@vegaprotocol/wallet';
|
Feat/63 Deal ticket (#82)
* scaffold dealticket package, remove trading views from react-helpers
* add deal ticket component, add intent utils, expand dialog and form group styles
* add splash component, show market not found message if market doesnt exist
* tidy up error handling
* add handleError method for vega tx hook
* add better testname for provider test, flesh out tests a bit more for deal ticket
* Add unit tests for useVegaTransaction and useOrderSubmit hooks
* add wrapper component for order dialog styles
* add vega styled loader to ui toolkit and use in order dialog
* add title prop to order dialog
* split limit and market tickets into own files
* add button radio component
* revert dialog styles
* move splash component to ui-toolkit, add story
* convert intent to enum
* Make button always type=button unless type prop is passed
* inline filter logic for tif selector
* add date-fns, add datetime to helpers
* add order types to wallet package, make price undefined if order type is market
* use enums in deal ticket logic
* tidy up order state by moving submit and transaction hooks out of deal ticket
* add comment for dialog styles
* remove decimal from price input
* add types package, delete old generated types from trading project
* rename types package to graphql
* update generate command to point to correct locations
* fix use order submit test
* use intent shadow helper
* remove date-fns and format manually, update submit button error to use input-error
* remove stray console.log
2022-03-17 19:35:46 +00:00
|
|
|
import { useState, useCallback } from 'react';
|
|
|
|
|
|
|
|
export interface Order {
|
|
|
|
size: string;
|
|
|
|
type: OrderType;
|
|
|
|
timeInForce: OrderTimeInForce;
|
|
|
|
side: OrderSide | null;
|
|
|
|
price?: string;
|
|
|
|
expiration?: Date;
|
|
|
|
}
|
|
|
|
|
|
|
|
export type UpdateOrder = (order: Partial<Order>) => void;
|
|
|
|
|
|
|
|
export const useOrderState = (defaultOrder: Order): [Order, UpdateOrder] => {
|
|
|
|
const [order, setOrder] = useState<Order>(defaultOrder);
|
|
|
|
|
|
|
|
const updateOrder = useCallback((orderUpdate: Partial<Order>) => {
|
|
|
|
setOrder((curr) => {
|
|
|
|
// Type is switching to market so return new market order object with correct defaults
|
|
|
|
if (
|
|
|
|
orderUpdate.type === OrderType.Market &&
|
|
|
|
curr.type !== OrderType.Market
|
|
|
|
) {
|
|
|
|
// Check if provided TIF or current TIF is valid for a market order and default
|
|
|
|
// to IOC if its not
|
|
|
|
|
|
|
|
const isTifValid = (tif: OrderTimeInForce) => {
|
|
|
|
return tif === OrderTimeInForce.FOK || tif === OrderTimeInForce.IOC;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Default
|
|
|
|
let timeInForce = OrderTimeInForce.IOC;
|
|
|
|
|
|
|
|
if (orderUpdate.timeInForce) {
|
|
|
|
if (isTifValid(orderUpdate.timeInForce)) {
|
|
|
|
timeInForce = orderUpdate.timeInForce;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (isTifValid(curr.timeInForce)) {
|
|
|
|
timeInForce = curr.timeInForce;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
type: orderUpdate.type,
|
|
|
|
size: orderUpdate.size || curr.size,
|
|
|
|
side: orderUpdate.side || curr.side,
|
|
|
|
timeInForce,
|
|
|
|
price: undefined,
|
|
|
|
expiration: undefined,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Type is switching to limit so return new order object with correct defaults
|
|
|
|
if (
|
|
|
|
orderUpdate.type === OrderType.Limit &&
|
|
|
|
curr.type !== OrderType.Limit
|
|
|
|
) {
|
|
|
|
return {
|
|
|
|
type: orderUpdate.type,
|
|
|
|
size: orderUpdate.size || curr.size,
|
|
|
|
side: orderUpdate.side || curr.side,
|
|
|
|
timeInForce: orderUpdate.timeInForce || curr.timeInForce,
|
|
|
|
price: orderUpdate.price || '0',
|
|
|
|
expiration: orderUpdate.expiration || undefined,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
...curr,
|
|
|
|
...orderUpdate,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
return [order, updateOrder];
|
|
|
|
};
|