show offers on /markets, fixes for pairs without trades
This commit is contained in:
parent
92a38a8c76
commit
64bcead0b2
5 changed files with 49 additions and 19 deletions
|
@ -37,6 +37,7 @@ const formatPrice = (
|
||||||
showSign = false,
|
showSign = false,
|
||||||
useQuote = true,
|
useQuote = true,
|
||||||
) => {
|
) => {
|
||||||
|
if (!price) return Number.NaN;
|
||||||
const calculatedPrice = getPrice(price, currency, useQuote);
|
const calculatedPrice = getPrice(price, currency, useQuote);
|
||||||
return (
|
return (
|
||||||
(showSign
|
(showSign
|
||||||
|
|
|
@ -71,7 +71,7 @@ Object.groupBy ||= (values, keyFinder) => {
|
||||||
margin-top:auto;
|
margin-top:auto;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
}
|
}
|
||||||
.col{
|
.col {
|
||||||
display:flex;
|
display:flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -108,12 +108,15 @@ Object.groupBy ||= (values, keyFinder) => {
|
||||||
text-align:right;
|
text-align:right;
|
||||||
padding:.3em;
|
padding:.3em;
|
||||||
}
|
}
|
||||||
th:first-child, td:first-child{
|
th:first-child, td:first-child {
|
||||||
text-align:left;
|
text-align:left;
|
||||||
}
|
}
|
||||||
tr:nth-child(2n){
|
tbody tr:nth-child(2n) {
|
||||||
background-color: #0002;
|
background-color: #0002;
|
||||||
}
|
}
|
||||||
|
tfoot {
|
||||||
|
border-top: #0004 double 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +124,7 @@ Object.groupBy ||= (values, keyFinder) => {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color:#f60;
|
color:#f60;
|
||||||
}
|
}
|
||||||
a:hover{
|
a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
.price {
|
.price {
|
||||||
|
@ -159,7 +162,7 @@ Object.groupBy ||= (values, keyFinder) => {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap:.2em;
|
gap:.2em;
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 600px){
|
@media only screen and (max-width: 600px) {
|
||||||
.header > * {
|
.header > * {
|
||||||
width:initial;
|
width:initial;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,11 +72,13 @@ const BUY_SELL = isMoneroQuote(market) ? ["SELL", "BUY"] : ["BUY", "SELL"];
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col card" bind:clientWidth={w}>
|
<div class="col card" bind:clientWidth={w}>
|
||||||
<h4>{marketPair}</h4>
|
<h4>{marketPair}</h4>
|
||||||
<span class="price">{formatPrice(data.trades?.[0]?.price, market, true, false)}</span>
|
<span class="price">{formatPrice(data.trades?.[0]?.price, market, true, false) || "-"}</span>
|
||||||
|
{#if data.trades?.length}
|
||||||
<Chart width={w-20} height={500} container={{class:"row"}} layout={chartLayout} grid={gridLayout}>
|
<Chart width={w-20} height={500} container={{class:"row"}} layout={chartLayout} grid={gridLayout}>
|
||||||
<CandlestickSeries data={trades} reactive={true} priceFormat={{minMove:10**-precision, precision:precision}}></CandlestickSeries>
|
<CandlestickSeries data={trades} reactive={true} priceFormat={{minMove:10**-precision, precision:precision}}></CandlestickSeries>
|
||||||
<TimeScale rightBarStaysOnScroll={true} rightOffset={0}/>
|
<TimeScale rightBarStaysOnScroll={true} rightOffset={0}/>
|
||||||
</Chart>
|
</Chart>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { trades } from "$lib/server/context";
|
import { offers, trades } from "$lib/server/context";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
export function load() {
|
export function load() {
|
||||||
return { trades: get(trades) };
|
return { trades: get(trades), offers: get(offers) };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<svelte:options runes={true} />
|
<svelte:options runes={true} />
|
||||||
<script>
|
<script>
|
||||||
import { formatPrice, getAsset } from "$lib/formatPrice";
|
import { crypto, fiat, formatPrice, getAsset } from "$lib/formatPrice";
|
||||||
import {
|
import {
|
||||||
Chart,
|
Chart,
|
||||||
HistogramSeries,
|
HistogramSeries,
|
||||||
|
@ -10,6 +10,18 @@ import {
|
||||||
} from "svelte-lightweight-charts";
|
} from "svelte-lightweight-charts";
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
|
|
||||||
|
let groupedTrades = Object.groupBy(data.trades, ({ currency }) => currency);
|
||||||
|
let markets = [...$fiat, ...$crypto]
|
||||||
|
.map((e) => {
|
||||||
|
return {
|
||||||
|
...e,
|
||||||
|
trades: groupedTrades[e.code],
|
||||||
|
offers: data.offers[e.code],
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter((e) => e.offers || e.trades);
|
||||||
|
|
||||||
let interval = $state("86400000");
|
let interval = $state("86400000");
|
||||||
let [volume, swaps] = $derived(
|
let [volume, swaps] = $derived(
|
||||||
(() => {
|
(() => {
|
||||||
|
@ -79,7 +91,8 @@ let w = $state();
|
||||||
<option value="3600000">Hourly</option>
|
<option value="3600000">Hourly</option>
|
||||||
<option value="86400000">Daily</option>
|
<option value="86400000">Daily</option>
|
||||||
<option value="604800000">Weekly</option>
|
<option value="604800000">Weekly</option>
|
||||||
</select> Volume</h4>
|
</select> Volume
|
||||||
|
</h4>
|
||||||
<Chart width={w-20} height={500} container={{class:"row"}} layout={chartLayout} grid={gridLayout}>
|
<Chart width={w-20} height={500} container={{class:"row"}} layout={chartLayout} grid={gridLayout}>
|
||||||
<LineSeries data={volume} reactive={true} priceFormat={{precision:2, minMove:.01}}>
|
<LineSeries data={volume} reactive={true} priceFormat={{precision:2, minMove:.01}}>
|
||||||
<PriceScale scaleMargins={{bottom:.4, top:.1}}/>
|
<PriceScale scaleMargins={{bottom:.4, top:.1}}/>
|
||||||
|
@ -99,18 +112,29 @@ let w = $state();
|
||||||
<tr>
|
<tr>
|
||||||
<th>Currency</th>
|
<th>Currency</th>
|
||||||
<th>Price</th>
|
<th>Price</th>
|
||||||
|
<th>Offers</th>
|
||||||
<th>Volume (XMR)</th>
|
<th>Volume (XMR)</th>
|
||||||
<th>Trades</th>
|
<th>Trades</th>
|
||||||
</tr>
|
</tr>
|
||||||
{#each Object.values(Object.groupBy(data.trades, ({currency}) => currency)).toSorted((a,b) => b.length - a.length || (b[0].currency < a[0].currency ? 1 : -1)).slice(0, 16) as market}
|
{#each Object.values(markets).toSorted((a,b) => (b.trades?.length||0) - (a.trades?.length||0) || (b.offers?.length||0) - (a.offers?.length||0) || (b.code < a.code ? 1 : -1)) as market}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="market/{market[0].currency}">{getAsset(market[0].currency).name} ({market[0].currency})</a></td>
|
<td><a href="market/{market.code}">{getAsset(market.code).name} ({market.code})</a></td>
|
||||||
<td>{formatPrice(market[0].price, market[0].currency, true, false)}</td>
|
<td>{formatPrice(market.trades?.[0]?.price, market.code, true, false) || "-"}</td>
|
||||||
<td>{formatPrice(market.reduce((a,b) => a + b.xmrAmount, 0), "XMR", false, false)}</td>
|
<td>{market.offers?.length || "-"}</td>
|
||||||
<td>{market.length}</td>
|
<td>{formatPrice(market.trades?.reduce((a,b) => a + b.xmrAmount, 0), "XMR", false, false) || "-"}</td>
|
||||||
|
<td>{market.trades?.length || "-"}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td>{Object.values(data.offers).flat().length}</td>
|
||||||
|
<td>{formatPrice(data.trades.reduce((a,b) => a + b.xmrAmount, 0), "XMR", false, false)}</td>
|
||||||
|
<td>{data.trades.length}</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue