You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

203 lines
9.4 KiB

import {
Box,
Button,
Center,
Divider,
Flex,
HStack,
SimpleGrid,
StackDivider,
Text,
useToast,
VStack,
} from "@chakra-ui/react";
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 CfdTile from "./components/CfdTile";
import CurrencyInputField from "./components/CurrencyInputField";
import useLatestEvent from "./components/Hooks";
import NavLink from "./components/NavLink";
import OrderTile from "./components/OrderTile";
import { Cfd, Order, WalletInfo } from "./components/Types";
import Wallet from "./components/Wallet";
interface CfdSellOrderPayload {
price: number;
min_quantity: number;
max_quantity: number;
}
async function postCfdSellOrderRequest(payload: CfdSellOrderPayload) {
let res = await fetch(`/api/order/sell`, { method: "POST", body: JSON.stringify(payload), credentials: "include" });
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: "/api/feed", options: { withCredentials: true } });
const cfds = useLatestEvent<Cfd[]>(source, "cfds");
const order = useLatestEvent<Order>(source, "order");
console.log(cfds);
const walletInfo = useLatestEvent<WalletInfo>(source, "wallet");
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} direction={"column"}>
<Wallet walletInfo={walletInfo} />
<VStack spacing={5} shadow={"md"} padding={5} align={"stretch"} height={"100%"}>
<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>
);
}