Skip to content

Commit

Permalink
feat: add history
Browse files Browse the repository at this point in the history
  • Loading branch information
EchoDex committed Feb 20, 2024
1 parent d7e36de commit 1a46212
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 98 deletions.
2 changes: 1 addition & 1 deletion spark-frontend/src/components/TokenInput/TokenInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ const TokenInput: React.FC<IProps> = (props) => {
autofocus={focused}
decimals={props.decimals}
disabled={props.disabled}
displayDecimals={2}
displayDecimals={props.decimals}
max={props.max?.toString()}
placeholder="0.00"
renderInput={(props, ref) => (
Expand Down
32 changes: 27 additions & 5 deletions spark-frontend/src/entity/SpotMarketTrade.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { DEFAULT_DECIMALS } from "@src/constants";
import dayjs, { Dayjs } from "dayjs";
import { Nullable } from "tsdef";

import { DEFAULT_DECIMALS, TOKENS_BY_SYMBOL } from "@src/constants";
import BN from "@src/utils/BN";

import { Token } from "./Token";
Expand All @@ -7,33 +10,52 @@ interface SpotMarketTradeParams {
id: string;
baseToken: Token;
matcher: string;
seller: string;
buyer: string;
tradeAmount: BN;
price: BN;
timestamp: number;
userAddress: string;
}

const getType = (userAddress: string, buyer: string, seller: string) => {
const address = userAddress.toLowerCase();
return address === seller.toLowerCase() ? "SELL" : address === buyer.toLowerCase() ? "BUY" : null;
};

export class SpotMarketTrade {
readonly id: SpotMarketTradeParams["id"];
readonly baseToken: SpotMarketTradeParams["baseToken"];
readonly matcher: SpotMarketTradeParams["matcher"];
readonly seller: SpotMarketTradeParams["seller"];
readonly buyer: SpotMarketTradeParams["buyer"];
readonly tradeAmount: SpotMarketTradeParams["tradeAmount"];
readonly price: SpotMarketTradeParams["price"];
readonly timestamp: SpotMarketTradeParams["timestamp"];
readonly timestamp: Dayjs;
readonly quoteToken = TOKENS_BY_SYMBOL.USDC;
readonly type: Nullable<"SELL" | "BUY"> = null;

constructor(params: SpotMarketTradeParams) {
this.id = params.id;
this.baseToken = params.baseToken;
this.matcher = params.matcher;
this.seller = params.seller;
this.buyer = params.buyer;
this.tradeAmount = params.tradeAmount;
this.price = params.price;
this.timestamp = params.timestamp;
this.timestamp = dayjs.unix(params.timestamp);
this.type = getType(params.userAddress, this.buyer, this.seller);
}

get formatPrice() {
return BN.formatUnits(this.price, DEFAULT_DECIMALS).toFormat(2);
return BN.formatUnits(this.price, DEFAULT_DECIMALS).toSignificant(2);
}

get formatTradeAmount() {
return BN.formatUnits(this.price, this.baseToken.decimals).toFormat(2);
return BN.formatUnits(this.tradeAmount, this.baseToken.decimals).toSignificant(2);
}

get marketSymbol() {
return `${this.baseToken.symbol}-${this.quoteToken.symbol}`;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const MAX_TABLE_HEIGHT = {
const TABS = [
{ title: "ORDERS", disabled: false },
{ title: "BALANCES", disabled: false },
// { title: "HISTORY", disabled: false },
{ title: "HISTORY", disabled: false },
];

const TABLE_SIZES_CONFIG = [
Expand Down Expand Up @@ -124,26 +124,26 @@ const BottomTablesInterfaceSpotImpl: React.FC<IProps> = observer(() => {
),
}));

// const getHistoryData = () =>
// vm.myOrdersHistory.map((order) => ({
// date: order.timestamp.format("DD MMM YY, HH:mm"),
// pair: order.marketSymbol,
// type: (
// <TableText color={order.type === "SELL" ? theme.colors.redLight : theme.colors.greenLight}>
// {order.type}
// </TableText>
// ),
// amount: (
// <SmartFlex center="y" gap="4px">
// <TableText primary>{order.baseSizeUnits.toSignificant(2)}</TableText>
// <TokenBadge>
// <Text>{order.baseToken.symbol}</Text>
// </TokenBadge>
// </SmartFlex>
// ),
// price: toCurrency(order.priceUnits.toSignificant(2)),
// filled: BN.ZERO.toString(),
// }));
const getHistoryData = () =>
vm.myOrdersHistory.map((order) => ({
date: order.timestamp.format("DD MMM YY, HH:mm"),
pair: order.marketSymbol,
type: (
<TableText color={order.type === "SELL" ? theme.colors.redLight : theme.colors.greenLight}>
{order.type}
</TableText>
),
amount: (
<SmartFlex center="y" gap="4px">
<TableText primary>{order.formatTradeAmount}</TableText>
<TokenBadge>
<Text>{order.baseToken.symbol}</Text>
</TokenBadge>
</SmartFlex>
),
price: toCurrency(order.formatPrice),
filled: order.formatTradeAmount,
}));

const getBalanceData = () =>
Array.from(balanceStore.balances)
Expand Down Expand Up @@ -189,10 +189,6 @@ const BottomTablesInterfaceSpotImpl: React.FC<IProps> = observer(() => {
{ord.type}
</TableText>
</SmartFlex>
<SmartFlex center="y">
<Text type={TEXT_TYPES.SUPPORTING}>Filled:</Text>
<Text color={theme.colors.textPrimary}>-</Text>
</SmartFlex>
</SmartFlex>
</MobileTableRowColumn>
<MobileTableRowColumn>
Expand All @@ -207,45 +203,50 @@ const BottomTablesInterfaceSpotImpl: React.FC<IProps> = observer(() => {
</MobileTableOrderRow>
));

// const orderHistoryData = vm.myOrdersHistory.map((ord, i) => (
// <MobileTableOrderRow key={i + "mobile-history-row"}>
// <MobileTableRowColumn>
// <Text color={theme.colors.textPrimary} type={TEXT_TYPES.BUTTON_SECONDARY}>
// {ord.marketSymbol}
// </Text>
// <SmartFlex gap="2px" column>
// <Text type={TEXT_TYPES.SUPPORTING}>Amount</Text>
// <SmartFlex center="y" gap="4px">
// <Text color={theme.colors.textPrimary}>{ord.baseSizeUnits.toSignificant(2)}</Text>
// <TokenBadge>
// <Text>{ord.baseToken.symbol}</Text>
// </TokenBadge>
// </SmartFlex>
// </SmartFlex>
// </MobileTableRowColumn>
// <MobileTableRowColumn>
// <Text color={theme.colors.textPrimary}>Active</Text>
// <SmartFlex gap="2px" column>
// <SmartFlex center="y" gap="4px">
// <Text type={TEXT_TYPES.SUPPORTING}>Side:</Text>
// <TableText color={ord.type === "SELL" ? theme.colors.redLight : theme.colors.greenLight}>
// {ord.type}
// </TableText>
// </SmartFlex>
// <SmartFlex center="y">
// <Text type={TEXT_TYPES.SUPPORTING}>Filled:</Text>
// <Text color={theme.colors.textPrimary}>-</Text>
// </SmartFlex>
// </SmartFlex>
// </MobileTableRowColumn>
// <MobileTableRowColumn>
// <SmartFlex alignItems="flex-end" gap="2px" column>
// <Text type={TEXT_TYPES.SUPPORTING}>Price:</Text>
// <Text color={theme.colors.textPrimary}>{toCurrency(ord.priceUnits.toSignificant(2))}</Text>
// </SmartFlex>
// </MobileTableRowColumn>
// </MobileTableOrderRow>
// ));
const orderHistoryData = vm.myOrdersHistory.map((ord, i) => (
<MobileTableOrderRow key={i + "mobile-history-row"}>
<MobileTableRowColumn>
<Text color={theme.colors.textPrimary} type={TEXT_TYPES.BUTTON_SECONDARY}>
{ord.marketSymbol}
</Text>
<SmartFlex gap="2px" column>
<Text type={TEXT_TYPES.SUPPORTING}>Amount</Text>
<SmartFlex center="y" gap="4px">
<Text color={theme.colors.textPrimary}>{ord.formatTradeAmount}</Text>
<TokenBadge>
<Text>{ord.baseToken.symbol}</Text>
</TokenBadge>
</SmartFlex>
</SmartFlex>
</MobileTableRowColumn>
<MobileTableRowColumn>
<Text color={theme.colors.textPrimary}>Complete</Text>
<SmartFlex gap="2px" column>
<SmartFlex center="y" gap="4px">
<Text type={TEXT_TYPES.SUPPORTING}>Side:</Text>
<TableText color={ord.type === "SELL" ? theme.colors.redLight : theme.colors.greenLight}>
{ord.type}
</TableText>
</SmartFlex>
<SmartFlex center="y" gap="4px">
<Text type={TEXT_TYPES.SUPPORTING}>Filled:</Text>
<SmartFlex center="y" gap="4px">
<Text color={theme.colors.textPrimary}>{ord.formatTradeAmount}</Text>
<TokenBadge>
<Text>{ord.baseToken.symbol}</Text>
</TokenBadge>
</SmartFlex>
</SmartFlex>
</SmartFlex>
</MobileTableRowColumn>
<MobileTableRowColumn>
<SmartFlex alignItems="flex-end" gap="2px" column>
<Text type={TEXT_TYPES.SUPPORTING}>Price:</Text>
<Text color={theme.colors.textPrimary}>{toCurrency(ord.formatPrice)}</Text>
</SmartFlex>
</MobileTableRowColumn>
</MobileTableOrderRow>
));

const balanceData = Array.from(balanceStore.balances)
.filter(([, balance]) => balance && balance.gt(0))
Expand Down Expand Up @@ -275,7 +276,7 @@ const BottomTablesInterfaceSpotImpl: React.FC<IProps> = observer(() => {
);
});

const tabToData = [orderData, balanceData];
const tabToData = [orderData, balanceData, orderHistoryData];

return (
<SmartFlex width="100%" column>
Expand Down Expand Up @@ -318,7 +319,7 @@ const BottomTablesInterfaceSpotImpl: React.FC<IProps> = observer(() => {
};

useEffect(() => {
const tabToData = [getOrderData, getBalanceData];
const tabToData = [getOrderData, getBalanceData, getHistoryData];
setData(tabToData[tabIndex]());
}, [tabIndex, vm.myOrders, balanceStore.balances]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { ethers } from "ethers";
import { makeAutoObservable, reaction, when } from "mobx";

import { SPOT_MARKET_ABI } from "@src/abi";
import { CONTRACT_ADDRESSES } from "@src/constants";
import { SpotMarketOrder } from "@src/entity";
import { CONTRACT_ADDRESSES, TOKENS_BY_ASSET_ID } from "@src/constants";
import { SpotMarketOrder, SpotMarketTrade } from "@src/entity";
import useVM from "@src/hooks/useVM";
import { fetchOrders } from "@src/services/SpotMarketService";
import { fetchOrders, fetchTrades } from "@src/services/SpotMarketService";
import { handleEvmErrors } from "@src/utils/handleEvmErrors";
import { RootStore, useStores } from "@stores";

Expand All @@ -22,7 +22,7 @@ export const useBottomTablesInterfaceSpotVM = () => useVM(ctx);

class BottomTablesInterfaceSpotVM {
myOrders: SpotMarketOrder[] = [];
myOrdersHistory: SpotMarketOrder[] = [];
myOrdersHistory: SpotMarketTrade[] = [];
initialized: boolean = false;

isOrderCancelling = false;
Expand Down Expand Up @@ -73,30 +73,32 @@ class BottomTablesInterfaceSpotVM {

if (!tradeStore.market || !accountStore.address) return;

const { market } = tradeStore;

try {
const orders = await fetchOrders({
baseToken: tradeStore.market.baseToken.assetId,
baseToken: market.baseToken.assetId,
limit: 100,
trader: accountStore.address,
isActive: true,
});
this.setMySpotOrders(orders);

const ordersHistory = await fetchOrders({
baseToken: tradeStore.market.baseToken.assetId,
limit: 100,
trader: accountStore.address,
isActive: false,
});
this.setMySpotOrdersHistory(ordersHistory);
const ordersHistory = await fetchTrades(market.baseToken.assetId, 100, accountStore.address);

const token = TOKENS_BY_ASSET_ID[market.baseToken.assetId];

this.setMySpotOrdersHistory(
ordersHistory.map((t) => new SpotMarketTrade({ ...t, baseToken: token, userAddress: accountStore.address! })),
);
} catch (error) {
console.error(error);
}
};

private setMySpotOrders = (myOrders: SpotMarketOrder[]) => (this.myOrders = myOrders);

private setMySpotOrdersHistory = (myOrdersHistory: SpotMarketOrder[]) => (this.myOrdersHistory = myOrdersHistory);
private setMySpotOrdersHistory = (myOrdersHistory: SpotMarketTrade[]) => (this.myOrdersHistory = myOrdersHistory);

private setInitialized = (l: boolean) => (this.initialized = l);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { media } from "@src/themes/breakpoints";
import BN from "@src/utils/BN";
import hexToRgba from "@src/utils/hexToRgb";

import { ORDER_MODE, useCreateOrderSpotVM } from "../../LeftBlock/CreateOrderSpot/CreateOrderSpotVM";
import { ORDER_MODE, ORDER_TYPE, useCreateOrderSpotVM } from "../../LeftBlock/CreateOrderSpot/CreateOrderSpotVM";

import { useSpotOrderbookVM } from "./SpotOrderbookVM";

Expand Down Expand Up @@ -107,6 +107,7 @@ const SpotOrderBookImpl: React.FC<IProps> = observer(() => {
orderSpotVm.setOrderMode(orderMode);
orderSpotVm.setInputPrice(o.price);
orderSpotVm.setInputAmount(new BN(o.baseSize), true);
orderSpotVm.setOrderType(ORDER_TYPE.Limit);
}}
>
<VolumeBar type={type} volumePercent={volumePercent(o).times(100).toNumber()} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useCallback, useEffect, useState } from "react";
import { useTheme } from "@emotion/react";
import styled from "@emotion/styled";
import dayjs from "dayjs";
import { observer } from "mobx-react";

import { Column } from "@components/Flex";
Expand Down Expand Up @@ -60,7 +59,7 @@ const SpotTradesImpl: React.FC<IProps> = observer(() => {
{trade.formatTradeAmount}
</Text>
<Text color={theme.colors.textPrimary} type={TEXT_TYPES.BODY}>
{dayjs.unix(trade.timestamp).format("HH:mm:ss")}
{trade.timestamp.format("HH:mm:ss")}
</Text>
</Row>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class SpotTradesVM {
}

updateTrades = async () => {
const { tradeStore, initialized } = this.rootStore;
const { accountStore, tradeStore, initialized } = this.rootStore;

const market = tradeStore.market;

Expand All @@ -47,7 +47,9 @@ class SpotTradesVM {
// todo: to think about TokenStore
const token = TOKENS_BY_ASSET_ID[market.baseToken.assetId];

this.trades = data.map((t) => new SpotMarketTrade({ ...t, baseToken: token }));
this.trades = data.map(
(t) => new SpotMarketTrade({ ...t, baseToken: token, userAddress: accountStore.address! }),
);
} catch (error) {
console.error("Error with loading trades");
}
Expand Down
Loading

0 comments on commit 1a46212

Please sign in to comment.