Browse Source

Merge #826

826: A few frontend improvements r=da-kami a=bonomat

1. fix: improves reference price being undefined

2. fix: moves the alert box below the grid to allow for longer messages
old: 
![image](https://user-images.githubusercontent.com/224613/145105460-e4f5263e-db5c-4eec-bf60-523b08c2e227.png)


3. fix: `@da-kami` thought this was a cashing problem 🙈

4. fix: make the input full width
5. fix: makes the button size fix width

new

![image](https://user-images.githubusercontent.com/224613/145107756-b374788d-d7fd-4c1d-9edd-5c3dcc85bae1.png)
![image](https://user-images.githubusercontent.com/224613/145107782-2154e201-5ced-42dd-9690-28954025eb9a.png)


Co-authored-by: bonomat <philipp@hoenisch.at>
release/0.3.1
bors[bot] 3 years ago
committed by GitHub
parent
commit
d668736c2a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      maker-frontend/src/MakerApp.tsx
  2. 21
      taker-frontend/src/App.tsx
  3. 37
      taker-frontend/src/components/CloseButton.tsx
  4. 10
      taker-frontend/src/components/History.tsx
  5. 256
      taker-frontend/src/components/Trade.tsx

4
maker-frontend/src/MakerApp.tsx

@ -47,8 +47,8 @@ export default function App() {
const toast = useToast(); const toast = useToast();
let [minQuantity, setMinQuantity] = useState<string>("10"); let [minQuantity, setMinQuantity] = useState<string>("100");
let [maxQuantity, setMaxQuantity] = useState<string>("100"); let [maxQuantity, setMaxQuantity] = useState<string>("1000");
let [orderPrice, setOrderPrice] = useState<string>("0"); let [orderPrice, setOrderPrice] = useState<string>("0");
let [autoRefresh, setAutoRefresh] = useState(true); let [autoRefresh, setAutoRefresh] = useState(true);

21
taker-frontend/src/App.tsx

@ -43,22 +43,17 @@ export const App = () => {
const toast = useToast(); const toast = useToast();
useBackendMonitor(toast, 5000, "Please start the taker again to reconnect..."); // 5s timeout useBackendMonitor(toast, 5000, "Please start the taker again to reconnect..."); // 5s timeout
const { let [referencePrice, setReferencePrice] = useState<number>();
lastMessage, useWebSocket("wss://www.bitmex.com/realtime?subscribe=instrument:.BXBT", {
readyState,
} = useWebSocket("wss://www.bitmex.com/realtime?subscribe=instrument:.BXBT", {
// Will attempt to reconnect on all close events, such as server shutting down
shouldReconnect: () => true, shouldReconnect: () => true,
onMessage: (message) => {
const data: BXBTData[] = JSON.parse(message.data).data;
if (data && data[0]?.markPrice) {
setReferencePrice(data[0].markPrice);
}
},
}); });
let referencePrice;
if (readyState === 1 && lastMessage) {
const data: BXBTData[] = JSON.parse(lastMessage.data).data;
if (data && data[0]?.markPrice) {
referencePrice = data[0].markPrice;
}
}
let source = useEventSource({ source: "/api/feed" }); let source = useEventSource({ source: "/api/feed" });
const walletInfo = useLatestEvent<WalletInfo>(source, "wallet"); const walletInfo = useLatestEvent<WalletInfo>(source, "wallet");
const order = useLatestEvent<Order>(source, "order", intoOrder); const order = useLatestEvent<Order>(source, "order", intoOrder);

37
taker-frontend/src/components/CloseButton.tsx

@ -19,15 +19,34 @@ interface Props {
cfd: Cfd; cfd: Cfd;
request: (req: any) => void; request: (req: any) => void;
status: boolean; status: boolean;
action: String; isForceCloseButton: boolean;
buttonTitle: String;
} }
/// Button that can be used to trigger non-collaborative close if the maker is offline and collaborative close if the /// Button that can be used to trigger non-collaborative close if the maker is offline and collaborative close if the
/// maker is online. /// maker is online.
export default function CloseButton({ cfd, request, status, action }: Props) { export default function CloseButton({ cfd, request, status, buttonTitle, isForceCloseButton }: Props) {
const disableCloseButton = cfd.state.getGroup() === StateGroupKey.CLOSED const disableCloseButton = cfd.state.getGroup() === StateGroupKey.CLOSED
|| !(cfd.state.key === StateKey.OPEN); || !(cfd.state.key === StateKey.OPEN);
let popoverBody = <>
<Text>
This will close your position with the counterparty. The current exchange rate will determine your
profit/losses.
</Text>
</>;
if (isForceCloseButton) {
popoverBody = <>
<Text>
This will force close your position with the counterparty. The exchange rate at
</Text>
<Timestamp timestamp={cfd.expiry_timestamp} />
<Text>
will determine your profit/losses. It is likely that the rate will change until then.
</Text>
</>;
}
return <Box w={"45%"}> return <Box w={"45%"}>
<Popover <Popover
placement="bottom" placement="bottom"
@ -35,22 +54,16 @@ export default function CloseButton({ cfd, request, status, action }: Props) {
> >
{({ onClose }) => (<> {({ onClose }) => (<>
<PopoverTrigger> <PopoverTrigger>
<Button colorScheme={"blue"} disabled={disableCloseButton}>{action}</Button> <Button colorScheme={"blue"} disabled={disableCloseButton}>{buttonTitle}</Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent color="white" bg="blue.800" borderColor="blue.800"> <PopoverContent color="white" bg="blue.800" borderColor="blue.800">
<PopoverHeader pt={4} fontWeight="bold" border="0"> <PopoverHeader pt={4} fontWeight="bold" border="0">
{action} your position {buttonTitle} your position
</PopoverHeader> </PopoverHeader>
<PopoverArrow /> <PopoverArrow />
<PopoverCloseButton /> <PopoverCloseButton />
<PopoverBody> <PopoverBody>
<Text> {popoverBody}
This will {action.toLowerCase()} your position with the counterparty. The exchange rate at
</Text>
<Timestamp timestamp={cfd.expiry_timestamp} />
<Text>
will determine your profit/losses. It is likely that the rate will change until then.
</Text>
</PopoverBody> </PopoverBody>
<PopoverFooter <PopoverFooter
border="0" border="0"
@ -69,7 +82,7 @@ export default function CloseButton({ cfd, request, status, action }: Props) {
}} }}
isLoading={status} isLoading={status}
> >
{action} {buttonTitle}
</Button> </Button>
</PopoverFooter> </PopoverFooter>
</PopoverContent> </PopoverContent>

10
taker-frontend/src/components/History.tsx

@ -75,8 +75,14 @@ const CfdDetails = ({ cfd, connectedToMaker }: CfdDetailsProps) => {
let [commit, isCommiting] = usePostRequest(`/api/cfd/${cfd.order_id}/commit`); let [commit, isCommiting] = usePostRequest(`/api/cfd/${cfd.order_id}/commit`);
const closeButton = connectedToMaker.online const closeButton = connectedToMaker.online
? <CloseButton request={settle} status={isSettling} cfd={cfd} action="Close" /> ? <CloseButton request={settle} status={isSettling} cfd={cfd} buttonTitle="Close" isForceCloseButton={false} />
: <CloseButton request={commit} status={isCommiting} cfd={cfd} action="Force Close" />; : <CloseButton
request={commit}
status={isCommiting}
cfd={cfd}
buttonTitle="Force Close"
isForceCloseButton={true}
/>;
return ( return (
<HStack bg={useColorModeValue("gray.100", "gray.700")} rounded={5} padding={2}> <HStack bg={useColorModeValue("gray.100", "gray.700")} rounded={5} padding={2}>

256
taker-frontend/src/components/Trade.tsx

@ -156,133 +156,142 @@ export default function Trade({
} }
return ( return (
<Center> <VStack>
<Grid <Center>
templateRows="repeat(1, 1fr)" <Grid
templateColumns="repeat(1, 1fr)" templateRows="repeat(1, 1fr)"
gap={4} templateColumns="repeat(1, 1fr)"
> gap={4}
<GridItem colSpan={1}> >
<Center> <GridItem colSpan={1}>
<MotionBox <Center>
variants={{ <MotionBox
pulse: { variants={{
scale: [1, 1.05, 1], pulse: {
}, scale: [1, 1.05, 1],
}} },
// @ts-ignore: lint is complaining but should be fine :) }}
transition={{ // @ts-ignore: lint is complaining but should be fine :)
// type: "spring", transition={{
ease: "linear", // type: "spring",
duration: 2, ease: "linear",
repeat: Infinity, duration: 2,
}} repeat: Infinity,
animate={"pulse"} }}
> animate={"pulse"}
<Circle size="256px" bg={outerCircleBg}> >
<Circle size="180px" bg={innerCircleBg}> <Circle size="256px" bg={outerCircleBg}>
<MotionBox> <Circle size="180px" bg={innerCircleBg}>
<Skeleton isLoaded={!!referencePriceAsNumber && referencePriceAsNumber > 0}> <MotionBox>
<Text fontSize={"4xl"} as="b">{referencePrice}</Text> <Skeleton isLoaded={!!referencePriceAsNumber && referencePriceAsNumber > 0}>
</Skeleton> <Text fontSize={"4xl"} as="b">{referencePrice}</Text>
</MotionBox> </Skeleton>
</MotionBox>
</Circle>
</Circle> </Circle>
</Circle> </MotionBox>
</MotionBox> </Center>
</Center> </GridItem>
</GridItem> <GridItem colSpan={1}>
<GridItem colSpan={1}> <Quantity
<Quantity min={minQuantity}
min={minQuantity} max={maxQuantity}
max={maxQuantity} quantity={quantity}
quantity={quantity} onChange={onQuantityChange}
onChange={onQuantityChange} quantityIncrement={quantityIncrement}
quantityIncrement={quantityIncrement} />
/> </GridItem>
</GridItem> <GridItem colSpan={1}>
<GridItem colSpan={1}> <Leverage leverage={leverage} />
<Leverage leverage={leverage} /> </GridItem>
</GridItem> <GridItem colSpan={1}>
<GridItem colSpan={1}> <Margin margin={margin} />
<Margin margin={margin} /> </GridItem>
</GridItem> <GridItem colSpan={1}>
<GridItem colSpan={1}> <Center>
<Center> <ButtonGroup
<ButtonGroup variant="solid"
variant="solid" padding="3"
padding="3" spacing="6"
spacing="6" >
> <Button colorScheme="red" size="lg" disabled h={16} w={"40"}>
<Button colorScheme="red" size="lg" disabled h={16}> <VStack>
<VStack> <Text as="b">Short</Text>
<Text as="b">Short</Text> <Text fontSize={"sm"}>{quantity.replace("$", "")}@{askPrice}</Text>
<Text fontSize={"sm"}>{quantity.replace("$", "")}@{askPrice}</Text> </VStack>
</VStack> </Button>
</Button> <Button
<Button disabled={!canSubmit} colorScheme="green" size="lg" onClick={onOpen} h={16}> disabled={!canSubmit}
<VStack> colorScheme="green"
<Text as="b">Long</Text> size="lg"
<Text fontSize={"sm"}>{quantity.replace("$", "")}@{askPrice}</Text> onClick={onOpen}
</VStack> h={16}
</Button> w={"40"}
>
<VStack>
<Text as="b">Long</Text>
<Text fontSize={"sm"}>{quantity.replace("$", "")}@{askPrice}</Text>
</VStack>
</Button>
<Modal isOpen={isOpen} onClose={onClose}> <Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay /> <ModalOverlay />
<ModalContent> <ModalContent>
<ModalHeader> <ModalHeader>
Market buy <b>{quantity}</b> of BTC/USD @ <b>{askPrice}</b> Market buy <b>{quantity}</b> of BTC/USD @ <b>{askPrice}</b>
</ModalHeader> </ModalHeader>
<ModalCloseButton /> <ModalCloseButton />
<ModalBody> <ModalBody>
<Table variant="striped" colorScheme="gray" size="sm"> <Table variant="striped" colorScheme="gray" size="sm">
<TableCaption> <TableCaption>
By submitting, {margin} will be locked on-chain in a contract. By submitting, {margin} will be locked on-chain in a contract.
</TableCaption> </TableCaption>
<Tbody> <Tbody>
<Tr> <Tr>
<Td><Text as={"b"}>Margin</Text></Td> <Td><Text as={"b"}>Margin</Text></Td>
<Td>{margin}</Td> <Td>{margin}</Td>
</Tr> </Tr>
<Tr> <Tr>
<Td><Text as={"b"}>Leverage</Text></Td> <Td><Text as={"b"}>Leverage</Text></Td>
<Td>{leverage}</Td> <Td>{leverage}</Td>
</Tr> </Tr>
<Tr> <Tr>
<Td><Text as={"b"}>Liquidation Price</Text></Td> <Td><Text as={"b"}>Liquidation Price</Text></Td>
<Td>{liquidationPrice}</Td> <Td>{liquidationPrice}</Td>
</Tr> </Tr>
</Tbody> </Tbody>
</Table> </Table>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<HStack> <HStack>
<Button <Button
colorScheme="teal" colorScheme="teal"
isLoading={isLongSubmitting} isLoading={isLongSubmitting}
onClick={() => { onClick={() => {
const quantityAsNumber = quantity.replace("$", ""); const quantityAsNumber = quantity.replace("$", "");
let payload: CfdOrderRequestPayload = { let payload: CfdOrderRequestPayload = {
order_id: orderId!, order_id: orderId!,
quantity: Number.parseFloat(quantityAsNumber), quantity: Number.parseFloat(quantityAsNumber),
}; };
onLongSubmit(payload); onLongSubmit(payload);
onClose(); onClose();
}} }}
> >
Confirm Confirm
</Button> </Button>
</HStack> </HStack>
</ModalFooter> </ModalFooter>
</ModalContent> </ModalContent>
</Modal> </Modal>
</ButtonGroup> </ButtonGroup>
</Center> </Center>
{alertBox} </GridItem>
</GridItem> </Grid>
</Grid> </Center>
</Center> {alertBox}
</VStack>
); );
} }
@ -307,6 +316,7 @@ function Quantity({ min, max, onChange, quantity, quantityIncrement }: QuantityP
step={quantityIncrement} step={quantityIncrement}
onChange={onChange} onChange={onChange}
value={quantity} value={quantity}
w={"100%"}
> >
<NumberInputField /> <NumberInputField />
<NumberInputStepper> <NumberInputStepper>

Loading…
Cancel
Save