Browse Source

Merge #307

307: Setting boundaries r=bonomat a=bonomat

This improves the UX slightly as the user knows what is the min and max amount. 

The UI will default to min amount.



Co-authored-by: Philipp Hoenisch <philipp@hoenisch.at>
refactor/no-log-handler
bors[bot] 3 years ago
committed by GitHub
parent
commit
3a846c8455
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      daemon/src/maker_cfd.rs
  2. 2
      daemon/src/model.rs
  3. 30
      frontend/src/TakerApp.tsx
  4. 9
      frontend/src/components/CurrencyInputField.tsx

15
daemon/src/maker_cfd.rs

@ -525,7 +525,18 @@ impl Actor {
}
};
// 2. Insert CFD in DB
// 2. check if order has acceptable amounts
if quantity < current_order.min_quantity || quantity > current_order.max_quantity {
self.takers
.do_send_async(maker_inc_connections::TakerMessage {
taker_id,
command: TakerCommand::NotifyOrderRejected { id: order_id },
})
.await?;
return Ok(());
}
// 3. Insert CFD in DB
let cfd = Cfd::new(
current_order.clone(),
quantity,
@ -541,7 +552,7 @@ impl Actor {
self.cfd_feed_actor_inbox
.send(load_all_cfds(&mut conn).await?)?;
// 3. Remove current order
// 4. Remove current order
self.current_order_id = None;
self.takers
.do_send_async(maker_inc_connections::BroadcastOrder(None))

2
daemon/src/model.rs

@ -13,7 +13,7 @@ use uuid::Uuid;
pub mod cfd;
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]
pub struct Usd(pub Decimal);
impl Usd {

30
frontend/src/TakerApp.tsx

@ -15,7 +15,7 @@ import {
useToast,
VStack,
} from "@chakra-ui/react";
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { useAsync } from "react-async";
import { useEventSource } from "react-sse-hooks";
import { CfdTable } from "./components/cfdtables/CfdTable";
@ -58,6 +58,8 @@ async function getMargin(payload: MarginRequestPayload): Promise<MarginResponse>
}
export default function App() {
const toast = useToast();
document.title = "Hermes Taker";
let source = useEventSource({ source: "/api/feed" });
@ -67,9 +69,11 @@ export default function App() {
const order = useLatestEvent<Order>(source, "order", intoOrder);
const walletInfo = useLatestEvent<WalletInfo>(source, "wallet");
const toast = useToast();
let [quantity, setQuantity] = useState("0");
let [margin, setMargin] = useState("0");
let [userHasEdited, setUserHasEdited] = useState(false);
let quantityToShow = userHasEdited ? quantity : (order?.min_quantity.toString() || "0");
let { run: calculateMargin } = useAsync({
deferFn: async ([payload]: any[]) => {
@ -90,6 +94,23 @@ export default function App() {
},
});
useEffect(() => {
if (!order) {
return;
}
let quantity = quantityToShow ? Number.parseFloat(quantityToShow) : 0;
let payload: MarginRequestPayload = {
leverage: order.leverage,
price: order.price,
quantity,
};
calculateMargin(payload);
}, // Eslint demands us to include `calculateMargin` in the list of dependencies.
// We don't want that as we will end up in an endless loop. It is safe to ignore `calculateMargin` because
// nothing in `calculateMargin` depends on outside values, i.e. is guaranteed to be stable.
// eslint-disable-next-line react-hooks/exhaustive-deps
[margin, quantityToShow, order]);
const format = (val: any) => `$` + val;
const parse = (val: any) => val.replace(/^\$/, "");
@ -135,6 +156,7 @@ export default function App() {
<Text>Quantity:</Text>
<CurrencyInputField
onChange={(valueString: string) => {
setUserHasEdited(true);
setQuantity(parse(valueString));
if (!order) {
return;
@ -147,7 +169,9 @@ export default function App() {
};
calculateMargin(payload);
}}
value={format(quantity)}
value={format(quantityToShow)}
min={order?.min_quantity}
max={order?.max_quantity}
/>
<Text>Margin in BTC:</Text>

9
frontend/src/components/CurrencyInputField.tsx

@ -11,18 +11,27 @@ import React from "react";
interface CurrencyInputFieldProps {
onChange: any;
value: StringOrNumber | undefined;
min?: number;
max?: number;
}
export default function CurrencyInputField(
{
onChange,
value,
min,
max,
}: CurrencyInputFieldProps,
) {
let minAmount = min || 0;
let maxAmount = max || Number.MAX_SAFE_INTEGER;
return (
<NumberInput
onChange={onChange}
value={value}
defaultValue={minAmount}
min={minAmount}
max={maxAmount}
>
<NumberInputField />
<NumberInputStepper>

Loading…
Cancel
Save