Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"pnpm": ">=9.7.0"
},
"dependencies": {
"@compolabs/spark-orderbook-ts-sdk": "^1.8.2",
"@compolabs/spark-orderbook-ts-sdk": "^1.8.4",
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"@fuels/connectors": "^0.9.1",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,31 @@ import SizedBox from "@components/SizedBox";
import Text, { TEXT_TYPES } from "@src/components/Text";

import { SpotOrderBook } from "./SpotOrderBook/SpotOrderBook";
import { SpotOrderbookVMProvider } from "./SpotOrderBook/SpotOrderbookVM";
import { SpotTrades } from "./SpotTrades/SpotTrades";
import { SpotTradesVMProvider } from "./SpotTrades/SpotTradesVM";

const OrderbookAndTradesInterface: React.FC = () => {
const [isOrderbook, setIsOrderbook] = useState(true);

return (
<SpotOrderbookVMProvider>
<SpotTradesVMProvider>
<Root>
<ButtonGroup style={{ padding: "0 12px" }}>
<Button active={isOrderbook} onClick={() => setIsOrderbook(true)}>
<Text primary={isOrderbook} type={TEXT_TYPES.BUTTON_SECONDARY}>
orderbook
</Text>
</Button>
<Button active={!isOrderbook} onClick={() => setIsOrderbook(false)}>
<Text primary={!isOrderbook} type={TEXT_TYPES.BUTTON_SECONDARY}>
trades
</Text>
</Button>
</ButtonGroup>
<SizedBox height={8} />
{isOrderbook ? <SpotOrderBook /> : <SpotTrades />}
</Root>
</SpotTradesVMProvider>
</SpotOrderbookVMProvider>
<SpotTradesVMProvider>
<Root>
<ButtonGroup style={{ padding: "0 12px" }}>
<Button active={isOrderbook} onClick={() => setIsOrderbook(true)}>
<Text primary={isOrderbook} type={TEXT_TYPES.BUTTON_SECONDARY}>
orderbook
</Text>
</Button>
<Button active={!isOrderbook} onClick={() => setIsOrderbook(false)}>
<Text primary={!isOrderbook} type={TEXT_TYPES.BUTTON_SECONDARY}>
trades
</Text>
</Button>
</ButtonGroup>
<SizedBox height={8} />
{isOrderbook ? <SpotOrderBook /> : <SpotTrades />}
</Root>
</SpotTradesVMProvider>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import { useStores } from "@stores";

import { ORDER_MODE, useCreateOrderVM } from "../../RightBlock/CreateOrder/CreateOrderVM";

import { useSpotOrderbookVM } from "./SpotOrderbookVM";

interface IProps extends HTMLAttributes<HTMLDivElement> {}

export enum SPOT_ORDER_FILTER {
Expand All @@ -43,7 +41,7 @@ const SPOT_SETTINGS_ICONS = {
};

export const SpotOrderBook: React.FC<IProps> = observer(() => {
const vm = useSpotOrderbookVM();
const { spotOrderBookStore } = useStores();
const orderSpotVm = useCreateOrderVM();
const media = useMedia();
const theme = useTheme();
Expand All @@ -53,18 +51,19 @@ export const SpotOrderBook: React.FC<IProps> = observer(() => {
const [isSettingsOpen, openSettings, closeSettings] = useFlag();

useEffect(() => {
vm.calcSize(media.mobile);
spotOrderBookStore.calcSize(media.mobile);
}, [media.mobile]);

const handleCalcSize = useCallback(() => {
vm.calcSize(media.mobile);
spotOrderBookStore.calcSize(media.mobile);
}, [media.mobile]);

useEventListener("resize", handleCalcSize);

const isOrderBookEmpty = vm.allBuyOrders.length === 0 && vm.allSellOrders.length === 0;
const isOrderBookEmpty =
spotOrderBookStore.allBuyOrders.length === 0 && spotOrderBookStore.allSellOrders.length === 0;

if (vm.isOrderBookLoading && isOrderBookEmpty) {
if (spotOrderBookStore.isOrderBookLoading && isOrderBookEmpty) {
return <Loader size={32} hideText />;
}

Expand All @@ -85,9 +84,9 @@ export const SpotOrderBook: React.FC<IProps> = observer(() => {
<SettingIcon
key={index}
alt="filter"
selected={vm.orderFilter === index}
selected={spotOrderBookStore.orderFilter === index}
src={value}
onClick={() => vm.setOrderFilter(index)}
onClick={() => spotOrderBookStore.setOrderFilter(index)}
/>
));
};
Expand All @@ -97,41 +96,45 @@ export const SpotOrderBook: React.FC<IProps> = observer(() => {
return (
<SpreadContainer>
<Text type={TEXT_TYPES.H} primary>
{vm.spreadPrice}
{spotOrderBookStore.spreadPrice}
</Text>
<Text>{`(${vm.spreadPercent}%)`}</Text>
<Text>{`(${spotOrderBookStore.spreadPercent}%)`}</Text>
</SpreadContainer>
);
}

return (
<SpreadContainer>
<Text type={TEXT_TYPES.SUPPORTING}>SPREAD</Text>
<Text primary>{vm.spreadPrice}</Text>
<Text>{`(${vm.spreadPercent}%) `}</Text>
<Text primary>{spotOrderBookStore.spreadPrice}</Text>
<Text>{`(${spotOrderBookStore.spreadPercent}%) `}</Text>
</SpreadContainer>
);
};

const indexOfDecimal = SPOT_DECIMAL_OPTIONS.indexOf(vm.decimalGroup);
const indexOfDecimal = SPOT_DECIMAL_OPTIONS.indexOf(spotOrderBookStore.decimalGroup);

const handleDecimalSelect = (index: string) => {
const value = SPOT_DECIMAL_OPTIONS[Number(index)];
vm.setDecimalGroup(value);
spotOrderBookStore.setDecimalGroup(value);
};

const renderOrders = (orders: SpotMarketOrder[], type: "sell" | "buy") => {
const orderMode = type === "sell" ? ORDER_MODE.BUY : ORDER_MODE.SELL;
const volumePercent = (ord: SpotMarketOrder) =>
type === "sell" ? ord.initialAmount.div(vm.totalSell) : ord.initialQuoteAmount.div(vm.totalBuy);
type === "sell"
? ord.initialAmount.div(spotOrderBookStore.totalSell)
: ord.initialQuoteAmount.div(spotOrderBookStore.totalBuy);
const color = type === "sell" ? theme.colors.redLight : theme.colors.greenLight;

return orders.map((o, index) => (
<OrderRow key={index + "order"} type={type} onClick={() => orderSpotVm.selectOrderbookOrder(o, orderMode)}>
<VolumeBar type={type} volumePercent={volumePercent(o).times(100).toNumber()} />
<Text primary>{o.currentAmountUnits.toFormat(4)}</Text>
<TextOverflow color={color}>{o.priceUnits.toFormat(vm.decimalGroup)}</TextOverflow>
<Text primary>{numeral(o.currentQuoteAmountUnits).format(`0.${"0".repeat(vm.decimalGroup)}a`)}</Text>
<TextOverflow color={color}>{o.priceUnits.toFormat(spotOrderBookStore.decimalGroup)}</TextOverflow>
<Text primary>
{numeral(o.currentQuoteAmountUnits).format(`0.${"0".repeat(spotOrderBookStore.decimalGroup)}a`)}
</Text>
</OrderRow>
));
};
Expand All @@ -156,33 +159,56 @@ export const SpotOrderBook: React.FC<IProps> = observer(() => {
<Text type={TEXT_TYPES.SUPPORTING}>{`Total ${market?.quoteToken.symbol}`}</Text>
</OrderBookHeader>
<Container
fitContent={vm.orderFilter === SPOT_ORDER_FILTER.SELL || vm.orderFilter === SPOT_ORDER_FILTER.BUY}
reverse={vm.orderFilter === SPOT_ORDER_FILTER.SELL}
fitContent={
spotOrderBookStore.orderFilter === SPOT_ORDER_FILTER.SELL ||
spotOrderBookStore.orderFilter === SPOT_ORDER_FILTER.BUY
}
reverse={spotOrderBookStore.orderFilter === SPOT_ORDER_FILTER.SELL}
>
{vm.orderFilter === SPOT_ORDER_FILTER.SELL_AND_BUY && (
{spotOrderBookStore.orderFilter === SPOT_ORDER_FILTER.SELL_AND_BUY && (
<Plug
length={vm.sellOrders.length < +vm.oneSizeOrders ? +vm.oneSizeOrders - 1 - vm.sellOrders.length : 0}
length={
spotOrderBookStore.sellOrders.length < +spotOrderBookStore.oneSizeOrders
? +spotOrderBookStore.oneSizeOrders - 1 - spotOrderBookStore.sellOrders.length
: 0
}
/>
)}
{vm.orderFilter === SPOT_ORDER_FILTER.SELL && (
{spotOrderBookStore.orderFilter === SPOT_ORDER_FILTER.SELL && (
<Plug
length={vm.sellOrders.length < +vm.amountOfOrders ? +vm.amountOfOrders - 1 - vm.sellOrders.length : 0}
length={
spotOrderBookStore.sellOrders.length < +spotOrderBookStore.amountOfOrders
? +spotOrderBookStore.amountOfOrders - 1 - spotOrderBookStore.sellOrders.length
: 0
}
/>
)}

{vm.orderFilter !== SPOT_ORDER_FILTER.BUY && renderOrders(vm.sellOrders, "sell")}
{spotOrderBookStore.orderFilter !== SPOT_ORDER_FILTER.BUY &&
renderOrders(spotOrderBookStore.sellOrders, "sell")}

{vm.orderFilter === SPOT_ORDER_FILTER.SELL_AND_BUY && renderSpread()}
{spotOrderBookStore.orderFilter === SPOT_ORDER_FILTER.SELL_AND_BUY && renderSpread()}

{vm.orderFilter !== SPOT_ORDER_FILTER.SELL && renderOrders(vm.buyOrders, "buy")}
{spotOrderBookStore.orderFilter !== SPOT_ORDER_FILTER.SELL &&
renderOrders(spotOrderBookStore.buyOrders, "buy")}

{vm.orderFilter === SPOT_ORDER_FILTER.BUY && (
{spotOrderBookStore.orderFilter === SPOT_ORDER_FILTER.BUY && (
<Plug
length={vm.buyOrders.length < +vm.amountOfOrders ? +vm.amountOfOrders - 1 - vm.buyOrders.length : 0}
length={
spotOrderBookStore.buyOrders.length < +spotOrderBookStore.amountOfOrders
? +spotOrderBookStore.amountOfOrders - 1 - spotOrderBookStore.buyOrders.length
: 0
}
/>
)}
{vm.orderFilter === SPOT_ORDER_FILTER.SELL_AND_BUY && (
<Plug length={vm.buyOrders.length < +vm.oneSizeOrders ? +vm.oneSizeOrders - 1 - vm.buyOrders.length : 0} />
{spotOrderBookStore.orderFilter === SPOT_ORDER_FILTER.SELL_AND_BUY && (
<Plug
length={
spotOrderBookStore.buyOrders.length < +spotOrderBookStore.oneSizeOrders
? +spotOrderBookStore.oneSizeOrders - 1 - spotOrderBookStore.buyOrders.length
: 0
}
/>
)}
</Container>

Expand All @@ -191,10 +217,10 @@ export const SpotOrderBook: React.FC<IProps> = observer(() => {
filterIcons={Object.entries(SPOT_SETTINGS_ICONS).map(([key, value]) => value)}
isOpen={isSettingsOpen}
selectedDecimal={String(indexOfDecimal)}
selectedFilter={vm.orderFilter}
selectedFilter={spotOrderBookStore.orderFilter}
onClose={closeSettings}
onDecimalSelect={handleDecimalSelect}
onFilterSelect={vm.setOrderFilter}
onFilterSelect={spotOrderBookStore.setOrderFilter}
/>
</OrderbookContainer>
</Root>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ const CreateOrder: React.FC = observer(() => {
};

const renderInstruction = () => {
if (settingsStore.orderType === ORDER_TYPE.Market) return <></>;
const handleChangeTimeInForce = (e: any) => {
settingsStore.setTimeInForce(e);
};
Expand Down
40 changes: 27 additions & 13 deletions src/screens/SpotScreen/RightBlock/CreateOrder/CreateOrderVM.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,18 @@ class CreateOrderVM {
() => oracleStore.prices,
() => {
const { orderType } = settingsStore;
const token = tradeStore.market?.baseToken;
const price = token?.priceFeed ? oracleStore.getTokenIndexPrice(token?.priceFeed) : BN.ZERO;

const { spotOrderBookStore } = this.rootStore;
const order = this.isSell
? spotOrderBookStore.buyOrders[0]
: spotOrderBookStore.sellOrders[spotOrderBookStore.sellOrders.length - 1];
if (orderType === ORDER_TYPE.Market) {
this.setInputPriceThrottle(price);
this.setInputPriceThrottle(order.price);
} else if (
orderType === ORDER_TYPE.Limit &&
this.inputPrice.isZero() &&
this.activeInput !== ACTIVE_INPUT.Price
) {
this.setInputPriceThrottle(price);
this.setInputPriceThrottle(order.price);
}
},
);
Expand Down Expand Up @@ -363,8 +364,6 @@ class CreateOrderVM {
...deposit,
};

console.log(order);

const data = await bcNetwork.createSpotOrderWithDeposit(order, marketContracts);
return data.transactionId;
};
Expand All @@ -383,27 +382,42 @@ class CreateOrderVM {
asset: market.baseToken.assetId ?? "",
status: ["Active"],
};
const isBuy = type === OrderType.Buy;

const oppositeOrderType = type === OrderType.Buy ? OrderType.Sell : OrderType.Buy;
const oppositeOrderType = isBuy ? OrderType.Sell : OrderType.Buy;
const orders = await bcNetwork.fetchSpotOrders({ ...params, orderType: oppositeOrderType });
let total = this.inputTotal;
let spend = BN.ZERO;
const orderList = orders
.map((el) => {
if (total.toNumber() < 0) {
return null;
}
spend = spend.plus(el.currentAmount);
total = total.minus(el.currentQuoteAmount);
return el;
})
.filter((el) => el !== null);

const price =
settingsStore.orderType === ORDER_TYPE.Market
? orders[orders.length - 1].price.toString()
? orderList[orderList.length - 1].price.toString()
: this.inputPrice.toString();

deposit = {
...deposit,
amountToSpend: this.inputAmount.toString(),
};

const order: FulfillOrderManyWithDepositParams = {
amount: this.inputAmount.toString(),
orderType: type,
limitType: settingsStore.timeInForce,
price,
orders: orders.map((el) => el.id),
orders: orderList.map((el) => el.id),
slippage: "10000",
...deposit,
};

console.log(order);

const data = await bcNetwork.fulfillOrderManyWithDeposit(order, marketContracts);
return data.transactionId;
};
Expand Down
5 changes: 1 addition & 4 deletions src/screens/SpotScreen/SpotScreenMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { media } from "@src/themes/breakpoints";
import { useStores } from "@stores";

import { SpotOrderBook } from "./OrderbookAndTradesInterface/SpotOrderBook/SpotOrderBook";
import { SpotOrderbookVMProvider } from "./OrderbookAndTradesInterface/SpotOrderBook/SpotOrderbookVM";
import CreateOrder from "./RightBlock/CreateOrder";
import MarketSelection from "./RightBlock/MarketSelection";
import MarketStatistics from "./MarketStatistics";
Expand All @@ -38,9 +37,7 @@ const SpotScreenMobile: React.FC = observer(() => {
return (
<MobileContent>
<ContentWrapper>
<SpotOrderbookVMProvider>
<SpotOrderBook />
</SpotOrderbookVMProvider>
<SpotOrderBook />
</ContentWrapper>
<ContentWrapper>
<CreateOrder />
Expand Down
Loading