|
1 |
| -import { useOrderbookStream } from '@orderly.network/hooks'; |
| 1 | +import { useOrderbookStream, useSymbolsInfo } from '@orderly.network/hooks'; |
2 | 2 | import { FC } from 'react';
|
3 | 3 |
|
4 | 4 | import { Spinner } from '.';
|
5 | 5 |
|
6 |
| -import { usdFormatter } from '~/utils'; |
| 6 | +import { getDecimalsFromTick } from '~/utils'; |
7 | 7 |
|
8 | 8 | export const Orderbook: FC<{ symbol: string }> = ({ symbol }) => {
|
9 | 9 | const [data, { isLoading }] = useOrderbookStream(symbol, undefined, {
|
10 | 10 | level: 10
|
11 | 11 | });
|
| 12 | + const symbolsInfo = useSymbolsInfo(); |
12 | 13 |
|
13 |
| - const [_, base, quote] = symbol.split('_'); |
14 |
| - |
15 |
| - if (isLoading) { |
| 14 | + if (isLoading || symbolsInfo.isNil) { |
16 | 15 | return (
|
17 | 16 | <div className="w-[20rem] h-full flex-self-center flex flex-justify-center">
|
18 | 17 | <Spinner size="4rem" />
|
19 | 18 | </div>
|
20 | 19 | );
|
21 | 20 | }
|
| 21 | + const symbolInfo = symbolsInfo[symbol](); |
| 22 | + const [_, base, quote] = symbol.split('_'); |
| 23 | + const [baseDecimals, quoteDecimals] = getDecimalsFromTick(symbolInfo); |
| 24 | + const baseFormatter = new Intl.NumberFormat('en-US', { maximumFractionDigits: baseDecimals }); |
| 25 | + const quoteFormatter = new Intl.NumberFormat('en-US', { maximumFractionDigits: quoteDecimals }); |
22 | 26 |
|
23 | 27 | let firstAsk: number;
|
24 | 28 | let firstBid: number;
|
25 | 29 | return (
|
26 |
| - <div className="grid gap-x-2 grid-cols-[5.5rem_5.5rem_8rem] font-bold font-size-[0.9rem] [&>*]:border-b [&>*]:border-[rgba(0, 0, 0, 0.2)] [&>*]:border-b-solid"> |
27 |
| - <div>Price ({quote})</div> |
28 |
| - <div>Quantity ({base})</div> |
29 |
| - <div className="text-end">Total ({base})</div> |
30 |
| - {data.asks |
31 |
| - ?.filter(([price]) => !Number.isNaN(price)) |
32 |
| - .map(([price, quantity, aggregated], index) => { |
33 |
| - if (firstAsk == null) { |
34 |
| - firstAsk = aggregated; |
35 |
| - } |
36 |
| - const gradient = (100 * aggregated) / firstAsk; |
37 |
| - return ( |
38 |
| - <div |
39 |
| - className="contents [&>*:nth-child(3n)]:text-end [&>*]:border-[rgba(255,255,255,0.5)] [&>*]:border-solid [&>*]:border-0 [&>*]:border-b-1" |
40 |
| - key={index} |
41 |
| - > |
42 |
| - <div className="color-[var(--color-light-red)]">{usdFormatter.format(price)}</div> |
43 |
| - <div>{quantity}</div> |
44 |
| - <div |
45 |
| - style={{ |
46 |
| - background: `linear-gradient(to left, rgba(161, 6, 6, 0.3) ${gradient}%, transparent ${gradient}%)` |
47 |
| - }} |
48 |
| - > |
49 |
| - {aggregated} |
50 |
| - </div> |
51 |
| - </div> |
52 |
| - ); |
53 |
| - })} |
54 |
| - {data.bids |
55 |
| - ?.filter(([price]) => !Number.isNaN(price)) |
56 |
| - .reverse() |
57 |
| - .map(([price, quantity, aggregated], index) => { |
58 |
| - if (firstBid == null) { |
59 |
| - firstBid = aggregated; |
60 |
| - } |
61 |
| - const gradient = (100 * aggregated) / firstBid; |
62 |
| - return ( |
63 |
| - <div |
64 |
| - className="contents [&>*:nth-child(3n)]:text-end [&>*]:border-[rgba(255,255,255,0.5)] [&>*]:border-solid [&>*]:border-0 [&>*]:border-b-1" |
65 |
| - key={index} |
66 |
| - > |
67 |
| - <div className="color-[var(--color-light-green)]">{usdFormatter.format(price)}</div> |
68 |
| - <div>{quantity}</div> |
69 |
| - <div |
70 |
| - style={{ |
71 |
| - background: `linear-gradient(to left, rgba(4, 109, 4, 0.3) ${gradient}%, transparent ${gradient}%)` |
72 |
| - }} |
73 |
| - > |
74 |
| - {aggregated} |
75 |
| - </div> |
76 |
| - </div> |
77 |
| - ); |
78 |
| - }) |
79 |
| - .reverse()} |
| 30 | + <div className="flex flex-col"> |
| 31 | + <div className="grid gap-x-2 grid-cols-[5.5rem_5.5rem_8rem] font-bold font-size-[0.9rem] [&>*]:border-b [&>*]:border-[rgba(0, 0, 0, 0.2)] [&>*]:border-b-solid"> |
| 32 | + <div>Price ({quote})</div> |
| 33 | + <div>Quantity ({base})</div> |
| 34 | + <div className="text-end">Total ({base})</div> |
| 35 | + </div> |
| 36 | + <div className="grid grid-rows-[1fr_1fr] flex-1"> |
| 37 | + <div className="self-end grid gap-x-2 grid-cols-[5.5rem_5.5rem_8rem] font-bold font-size-[0.9rem] [&>*]:border-b [&>*]:border-[rgba(0, 0, 0, 0.2)] [&>*]:border-b-solid"> |
| 38 | + {data.asks |
| 39 | + ?.filter(([price]) => !Number.isNaN(price)) |
| 40 | + .map(([price, quantity, aggregated], index) => { |
| 41 | + if (firstAsk == null) { |
| 42 | + firstAsk = aggregated; |
| 43 | + } |
| 44 | + const gradient = (100 * aggregated) / firstAsk; |
| 45 | + return ( |
| 46 | + <div |
| 47 | + className="contents [&>*:nth-child(3n)]:text-end [&>*]:border-[rgba(255,255,255,0.5)] [&>*]:border-solid [&>*]:border-0 [&>*]:border-b-1" |
| 48 | + key={index} |
| 49 | + > |
| 50 | + <div className="color-[var(--color-light-red)]"> |
| 51 | + {quoteFormatter.format(price)} |
| 52 | + </div> |
| 53 | + <div>{baseFormatter.format(quantity)}</div> |
| 54 | + <div |
| 55 | + style={{ |
| 56 | + background: `linear-gradient(to left, rgba(161, 6, 6, 0.3) ${gradient}%, transparent ${gradient}%)` |
| 57 | + }} |
| 58 | + > |
| 59 | + {baseFormatter.format(aggregated)} |
| 60 | + </div> |
| 61 | + </div> |
| 62 | + ); |
| 63 | + })} |
| 64 | + </div> |
| 65 | + <div className="self-start grid gap-x-2 grid-cols-[5.5rem_5.5rem_8rem] font-bold font-size-[0.9rem] [&>*]:border-b [&>*]:border-[rgba(0, 0, 0, 0.2)] [&>*]:border-b-solid"> |
| 66 | + {data.bids |
| 67 | + ?.filter(([price]) => !Number.isNaN(price)) |
| 68 | + .reverse() |
| 69 | + .map(([price, quantity, aggregated], index) => { |
| 70 | + if (firstBid == null) { |
| 71 | + firstBid = aggregated; |
| 72 | + } |
| 73 | + const gradient = (100 * aggregated) / firstBid; |
| 74 | + return ( |
| 75 | + <div |
| 76 | + className="contents [&>*:nth-child(3n)]:text-end [&>*]:border-[rgba(255,255,255,0.5)] [&>*]:border-solid [&>*]:border-0 [&>*]:border-b-1" |
| 77 | + key={index} |
| 78 | + > |
| 79 | + <div className="color-[var(--color-light-green)]"> |
| 80 | + {quoteFormatter.format(price)} |
| 81 | + </div> |
| 82 | + <div>{baseFormatter.format(quantity)}</div> |
| 83 | + <div |
| 84 | + style={{ |
| 85 | + background: `linear-gradient(to left, rgba(4, 109, 4, 0.3) ${gradient}%, transparent ${gradient}%)` |
| 86 | + }} |
| 87 | + > |
| 88 | + {baseFormatter.format(aggregated)} |
| 89 | + </div> |
| 90 | + </div> |
| 91 | + ); |
| 92 | + }) |
| 93 | + .reverse()} |
| 94 | + </div> |
| 95 | + </div> |
80 | 96 | </div>
|
81 | 97 | );
|
82 | 98 | };
|
0 commit comments