import { Box, Button, Center, Divider, Flex, HStack, SimpleGrid, StackDivider, Text, useToast, VStack, } from "@chakra-ui/react"; import axios from "axios"; import React, { useState } from "react"; import { useAsync } from "react-async"; import { Route, Routes } from "react-router-dom"; import { useEventSource } from "react-sse-hooks"; import "./App.css"; import OrderTile from "./components/OrderTile"; import CfdTile from "./components/CfdTile"; import CurrencyInputField from "./components/CurrencyInputField"; import useLatestEvent from "./components/Hooks"; import NavLink from "./components/NavLink"; import { Cfd, Order } from "./components/Types"; /* TODO: Change from localhost:8001 */ const BASE_URL = "http://localhost:8001"; interface CfdSellOrderPayload { price: number; min_quantity: number; max_quantity: number; } async function postCfdSellOrderRequest(payload: CfdSellOrderPayload) { let res = await axios.post(BASE_URL + `/order/sell`, JSON.stringify(payload)); if (!res.status.toString().startsWith("2")) { console.log("Status: " + res.status + ", " + res.statusText); throw new Error("failed to publish new order"); } } export default function App() { let source = useEventSource({ source: BASE_URL + "/maker-feed" }); const cfds = useLatestEvent<Cfd[]>(source, "cfds"); const order = useLatestEvent<Order>(source, "order"); console.log(cfds); const balance = useLatestEvent<number>(source, "balance"); const toast = useToast(); let [minQuantity, setMinQuantity] = useState<string>("100"); let [maxQuantity, setMaxQuantity] = useState<string>("1000"); let [orderPrice, setOrderPrice] = useState<string>("10000"); const format = (val: any) => `$` + val; const parse = (val: any) => val.replace(/^\$/, ""); let { run: makeNewCfdSellOrder, isLoading: isCreatingNewCfdOrder } = useAsync({ deferFn: async ([payload]: any[]) => { try { await postCfdSellOrderRequest(payload as CfdSellOrderPayload); } catch (e) { const description = typeof e === "string" ? e : JSON.stringify(e); toast({ title: "Error", description, status: "error", duration: 9000, isClosable: true, }); } }, }); return ( <Center marginTop={50}> <HStack> <Box marginRight={5}> <VStack align={"top"}> <NavLink text={"trade"} path={"trade"} /> <NavLink text={"wallet"} path={"wallet"} /> <NavLink text={"settings"} path={"settings"} /> </VStack> </Box> <Box width={1200} height="100%"> <Routes> <Route path="trade" element={<Flex direction={"row"} height={"100%"}> <Flex direction={"row"} width={"100%"}> <VStack spacing={5} shadow={"md"} padding={5} width={"100%"} divider={<StackDivider borderColor="gray.200" />} > <Box width={"100%"} overflow={"scroll"}> <SimpleGrid columns={2} spacing={10}> {cfds && cfds.map((cfd, index) => <CfdTile key={"cfd_" + index} index={index} cfd={cfd} /> )} </SimpleGrid> </Box> </VStack> </Flex> <Flex width={"50%"} marginLeft={5}> <VStack spacing={5} shadow={"md"} padding={5} align={"stretch"}> <HStack> <Text align={"left"}>Your balance:</Text> <Text>{balance}</Text> </HStack> <HStack> <Text align={"left"}>Current Price:</Text> <Text>{49000}</Text> </HStack> <HStack> <Text>Min Quantity:</Text> <CurrencyInputField onChange={(valueString: string) => setMinQuantity(parse(valueString))} value={format(minQuantity)} /> </HStack> <HStack> <Text>Min Quantity:</Text> <CurrencyInputField onChange={(valueString: string) => setMaxQuantity(parse(valueString))} value={format(maxQuantity)} /> </HStack> <HStack> <Text>Order Price:</Text> </HStack> <CurrencyInputField onChange={(valueString: string) => setOrderPrice(parse(valueString))} value={format(orderPrice)} /> <Text>Leverage:</Text> <Flex justifyContent={"space-between"}> <Button disabled={true}>x1</Button> <Button disabled={true}>x2</Button> <Button colorScheme="blue" variant="solid">x{5}</Button> </Flex> <VStack> <Center><Text>Maker UI</Text></Center> <Button disabled={isCreatingNewCfdOrder} variant={"solid"} colorScheme={"blue"} onClick={() => { let payload: CfdSellOrderPayload = { price: Number.parseFloat(orderPrice), min_quantity: Number.parseFloat(minQuantity), max_quantity: Number.parseFloat(maxQuantity), }; makeNewCfdSellOrder(payload); }} > {order ? "Update Sell Order" : "Create Sell Order"} </Button> <Divider /> <Box width={"100%"} overflow={"scroll"}> <Box> {order && <OrderTile order={order} />} </Box> </Box> </VStack> </VStack> </Flex> </Flex>} > </Route> <Route path="wallet" element={<Center height={"100%"} shadow={"md"}> <Box> <Text>Wallet</Text> </Box> </Center>} > </Route> <Route path="settings" element={<Center height={"100%"} shadow={"md"}> <Box> <Text>Settings</Text> </Box> </Center>} > </Route> </Routes> </Box> </HStack> </Center> ); }