77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
import React, { memo } from 'react';
|
|
import { useUpbitOrderbook } from '../../hooks/useUpbitOrderbook';
|
|
|
|
interface Props {
|
|
market: string;
|
|
onPick?: (price: number, rowType: 'ask' | 'bid') => void;
|
|
fillHeight?: boolean;
|
|
hideHeader?: boolean;
|
|
depth?: number;
|
|
}
|
|
|
|
function fmtPrice(p: number): string {
|
|
if (!Number.isFinite(p)) return '-';
|
|
return p >= 1000 ? p.toLocaleString('ko-KR', { maximumFractionDigits: 0 }) : p.toFixed(4);
|
|
}
|
|
|
|
function fmtSize(s: number): string {
|
|
if (!Number.isFinite(s)) return '-';
|
|
if (s >= 1000) return s.toLocaleString('ko-KR', { maximumFractionDigits: 2 });
|
|
return s.toFixed(4);
|
|
}
|
|
|
|
const PaperCompactOrderbook: React.FC<Props> = memo(({
|
|
market,
|
|
onPick,
|
|
fillHeight = false,
|
|
hideHeader = false,
|
|
depth = 8,
|
|
}) => {
|
|
const { orderbook } = useUpbitOrderbook(market);
|
|
const rowCount = fillHeight ? Math.max(depth, 12) : depth;
|
|
const asks = orderbook.asks.slice(0, rowCount).reverse();
|
|
const bids = orderbook.bids.slice(0, rowCount);
|
|
const maxSize = Math.max(
|
|
...asks.map(a => a.size),
|
|
...bids.map(b => b.size),
|
|
1,
|
|
);
|
|
const mid = bids[0]?.price ?? asks[asks.length - 1]?.price ?? 0;
|
|
|
|
return (
|
|
<div className={`ptd-ob${fillHeight ? ' ptd-ob--fill' : ''}`}>
|
|
{!hideHeader && <div className="ptd-ob-head">호가 (Depth)</div>}
|
|
<div className="ptd-ob-body">
|
|
{asks.map(a => (
|
|
<button
|
|
key={`a-${a.price}`}
|
|
type="button"
|
|
className="ptd-ob-row ptd-ob-row--ask"
|
|
onClick={() => onPick?.(a.price, 'ask')}
|
|
>
|
|
<span className="ptd-ob-bar" style={{ width: `${(a.size / maxSize) * 100}%` }} />
|
|
<span className="ptd-ob-price">{fmtPrice(a.price)}</span>
|
|
<span className="ptd-ob-size">{fmtSize(a.size)}</span>
|
|
</button>
|
|
))}
|
|
<div className="ptd-ob-mid">{mid ? fmtPrice(mid) : '—'}</div>
|
|
{bids.map(b => (
|
|
<button
|
|
key={`b-${b.price}`}
|
|
type="button"
|
|
className="ptd-ob-row ptd-ob-row--bid"
|
|
onClick={() => onPick?.(b.price, 'bid')}
|
|
>
|
|
<span className="ptd-ob-bar" style={{ width: `${(b.size / maxSize) * 100}%` }} />
|
|
<span className="ptd-ob-price">{fmtPrice(b.price)}</span>
|
|
<span className="ptd-ob-size">{fmtSize(b.size)}</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
});
|
|
|
|
PaperCompactOrderbook.displayName = 'PaperCompactOrderbook';
|
|
export default PaperCompactOrderbook;
|