Order
@@ -135,7 +150,8 @@ export function OrderBook() {
({token1Symbol})
-
+
+
{sells.map((props, index) => (
))}
diff --git a/src/app/components/order_input/LimitOrderInput.tsx b/src/app/components/order_input/LimitOrderInput.tsx
index 8133de0d..da8a95a3 100644
--- a/src/app/components/order_input/LimitOrderInput.tsx
+++ b/src/app/components/order_input/LimitOrderInput.tsx
@@ -18,9 +18,9 @@ import { AiOutlineInfoCircle } from "react-icons/ai";
import { BottomRightErrorLabel } from "components/BottomRightErrorLabel";
const POST_ONLY_TOOLTIP =
- "If your price is very close to the current market price, your limit order might fill immediately, " +
- "making you pay taker fees. This option prevents your order from being executed immediately, " +
- "guarantees that your order will make it to the order book and you will earn the liquidity provider fees.";
+ "Select 'POST ONLY' to ensure your order is added to the order book without matching existing orders. " +
+ "If your order can be partially or completely executed immediately, it will not be created. " +
+ "This option removes trading fees completely and ensures you receive the maker rebate.";
function NonTargetToken() {
const { token2, validationToken2, side } = useAppSelector(
@@ -246,7 +246,7 @@ export function LimitOrderInput() {
POST ONLY
diff --git a/src/app/redux/orderBookSlice.ts b/src/app/redux/orderBookSlice.ts
index 2187658b..eec8c3e6 100644
--- a/src/app/redux/orderBookSlice.ts
+++ b/src/app/redux/orderBookSlice.ts
@@ -20,6 +20,7 @@ export interface OrderBookState {
bestBuy: number | null;
spread: number | null;
spreadPercent: number | null;
+ grouping: number | null;
}
const initialState: OrderBookState = {
@@ -30,15 +31,14 @@ const initialState: OrderBookState = {
bestBuy: null,
spread: null,
spreadPercent: null,
+ grouping: 0,
};
export function toOrderBookRowProps(
adexOrderbookLines: adex.OrderbookLine[],
- side: "sell" | "buy"
+ side: "sell" | "buy",
+ grouping: number
): OrderBookRowProps[] {
- // this will drop the rows that do not fit into 8 buys/sells
- // TODO: implement pagination or scrolling
-
const props: OrderBookRowProps[] = [];
let adexRows = [...adexOrderbookLines]; // copy the array so we can mutate it
@@ -47,8 +47,39 @@ export function toOrderBookRowProps(
adexRows.reverse();
barColor = "hsl(var(--erc))";
}
- adexRows = adexRows.slice(0, 8); // Limit to 8 rows
-
+ let groupedArray;
+ if (grouping > 0) {
+ const roundToGroup = (num: number) => Math.round(num / grouping) * grouping;
+
+ if (adexRows.length > 0) {
+ groupedArray = adexRows.reduce((result: adex.OrderbookLine[], item) => {
+ const key = roundToGroup(item.price);
+ const foundItem = result.find(
+ (x: adex.OrderbookLine) => x.price === key
+ ); // note that we don't specify the type here
+ let existingItem: adex.OrderbookLine; // declare the variable without assigning it
+ if (foundItem !== undefined) {
+ // if the foundItem is not undefined, we can assign it safely
+ existingItem = foundItem;
+ existingItem.quantityRemaining += item.quantityRemaining;
+ existingItem.valueRemaining += item.valueRemaining;
+ existingItem.noOrders += item.noOrders;
+ existingItem.orders = existingItem.orders.concat(item.orders);
+ existingItem.total += item.total;
+ } else {
+ // If it's a new price, add it to the result
+ item.price = key;
+ result.push({ ...item });
+ }
+ return result;
+ }, []);
+ }
+ }
+ if (groupedArray != null) {
+ adexRows = groupedArray.slice(0, 11); //adexRows.slice(0, 11); // Limit to 11 rows
+ } else {
+ adexRows = adexRows.slice(0, 11);
+ }
let total = 0;
let maxTotal = 0;
for (let adexRow of adexRows) {
@@ -69,8 +100,8 @@ export function toOrderBookRowProps(
props[i].maxTotal = maxTotal;
}
- // If there are fewer than 8 orders, fill the remaining rows with empty values
- while (props.length < 8) {
+ // If there are fewer than 11 orders, fill the remaining rows with empty values
+ while (props.length < 11) {
props.push({ absentOrders: "\u00A0" });
}
@@ -93,15 +124,18 @@ export const orderBookSlice = createSlice({
reducers: {
updateAdex(state: OrderBookState, action: PayloadAction) {
const adexState = action.payload;
+ const grouping = state.grouping;
+
const sells = toOrderBookRowProps(
adexState.currentPairOrderbook.sells,
- "sell"
+ "sell",
+ grouping || 0
);
const buys = toOrderBookRowProps(
adexState.currentPairOrderbook.buys,
- "buy"
+ "buy",
+ grouping || 0
);
-
let bestSell = sells[sells.length - 1]?.price || null;
let bestBuy = buys[0]?.price || null;
@@ -120,6 +154,44 @@ export const orderBookSlice = createSlice({
state.bestSell = bestSell;
state.bestBuy = bestBuy;
},
+ setGrouping(state, action: PayloadAction) {
+ if (action.payload === null) {
+ state.grouping = 0;
+ } else if (action.payload < 0) {
+ state.grouping = 0;
+ } else {
+ state.grouping = action.payload;
+ }
+
+ const sells = toOrderBookRowProps(
+ adex.clientState.currentPairOrderbook.sells,
+ "sell",
+ state.grouping || 0
+ );
+ const buys = toOrderBookRowProps(
+ adex.clientState.currentPairOrderbook.buys,
+ "buy",
+ state.grouping || 0
+ );
+
+ let bestSell = sells[sells.length - 1]?.price || null;
+ let bestBuy = buys[0]?.price || null;
+
+ if (bestBuy !== null && bestSell !== null) {
+ const spread = bestSell - bestBuy;
+ if (bestBuy + bestSell !== 0) {
+ const spreadPercent = ((2 * spread) / (bestBuy + bestSell)) * 100;
+ state.spreadPercent = spreadPercent;
+ }
+ state.spread = spread;
+ }
+
+ state.sells = sells;
+ state.buys = buys;
+ state.lastPrice = adex.clientState.currentPairInfo.lastPrice;
+ state.bestSell = bestSell;
+ state.bestBuy = bestBuy;
+ },
},
});
diff --git a/src/app/redux/orderInputSlice.ts b/src/app/redux/orderInputSlice.ts
index f48de435..76dc4862 100644
--- a/src/app/redux/orderInputSlice.ts
+++ b/src/app/redux/orderInputSlice.ts
@@ -89,7 +89,7 @@ export const initialState: OrderInputState = {
token2: initialTokenInput,
validationToken2: initialValidationResult,
tab: OrderTab.MARKET,
- postOnly: true,
+ postOnly: false,
side: adex.OrderSide.BUY,
price: 0,
slippage: 0.01,