@xapy/orderbook 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/exchanges/coinex/index.cjs +109 -23
- package/dist/exchanges/coinex/index.cjs.map +1 -1
- package/dist/exchanges/coinex/index.d.cts +12 -4
- package/dist/exchanges/coinex/index.d.ts +12 -4
- package/dist/exchanges/coinex/index.js +109 -23
- package/dist/exchanges/coinex/index.js.map +1 -1
- package/dist/index.cjs +109 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +109 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1624,44 +1624,101 @@ function streamCoinexOrderbook(opts) {
|
|
|
1624
1624
|
const merger = new BookMerger();
|
|
1625
1625
|
let ws = null;
|
|
1626
1626
|
const stream = new OrderbookStream(() => ws?.close());
|
|
1627
|
-
const
|
|
1627
|
+
const subscribeDepth = JSON.stringify({
|
|
1628
1628
|
method: "depth.subscribe",
|
|
1629
1629
|
params: {
|
|
1630
|
-
// [market, limit, interval, diff_flag] — diff_flag=
|
|
1630
|
+
// [market, limit, interval, diff_flag] — diff_flag=true → snapshots only
|
|
1631
|
+
// (CoinEx flips the sense of the flag in V2; our handler treats every
|
|
1632
|
+
// frame as a snapshot to stay correct under either reading).
|
|
1631
1633
|
market_list: [[market, depth, "0", true]]
|
|
1632
1634
|
},
|
|
1633
1635
|
id: 1
|
|
1634
1636
|
});
|
|
1635
|
-
const
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1637
|
+
const subscribeBbo = JSON.stringify({
|
|
1638
|
+
method: "bbo.subscribe",
|
|
1639
|
+
params: { market_list: [market] },
|
|
1640
|
+
id: 2
|
|
1641
|
+
});
|
|
1642
|
+
let lastMerged = null;
|
|
1643
|
+
let lastTicker = null;
|
|
1644
|
+
const emitOverlayed = () => {
|
|
1645
|
+
if (!lastMerged) return;
|
|
1646
|
+
let bids = lastMerged.bids;
|
|
1647
|
+
let asks = lastMerged.asks;
|
|
1648
|
+
let timestamp = lastMerged.timestamp;
|
|
1649
|
+
let sequence = lastMerged.sequence;
|
|
1650
|
+
if (lastTicker) {
|
|
1651
|
+
bids = overlayBid2(bids, lastTicker.bid);
|
|
1652
|
+
asks = overlayAsk2(asks, lastTicker.ask);
|
|
1653
|
+
if (lastTicker.ts > timestamp) {
|
|
1654
|
+
timestamp = lastTicker.ts;
|
|
1655
|
+
sequence = Math.max(sequence, lastTicker.ts);
|
|
1656
|
+
}
|
|
1641
1657
|
}
|
|
1642
|
-
if (msg.id != null && !msg.method) return;
|
|
1643
|
-
if (msg.method !== "depth.update" || !msg.data) return;
|
|
1644
|
-
if (msg.data.market !== market) return;
|
|
1645
|
-
const d = msg.data.depth;
|
|
1646
|
-
const event = {
|
|
1647
|
-
kind: "snapshot",
|
|
1648
|
-
bids: d.bids.map(([p, s]) => ({ price: Number(p), size: Number(s) })),
|
|
1649
|
-
asks: d.asks.map(([p, s]) => ({ price: Number(p), size: Number(s) })),
|
|
1650
|
-
sequence: d.updated_at,
|
|
1651
|
-
timestamp: d.updated_at
|
|
1652
|
-
};
|
|
1653
|
-
const r = merger.apply(event);
|
|
1654
|
-
if (!r.ok) return;
|
|
1655
1658
|
const book = {
|
|
1656
1659
|
exchange: "coinex",
|
|
1657
1660
|
symbol: fromCoinexSymbol(market),
|
|
1658
1661
|
market: opts.market,
|
|
1662
|
+
bids,
|
|
1663
|
+
asks,
|
|
1664
|
+
timestamp,
|
|
1665
|
+
sequence
|
|
1666
|
+
};
|
|
1667
|
+
stream.emit("update", book);
|
|
1668
|
+
};
|
|
1669
|
+
const handleDepth = (d) => {
|
|
1670
|
+
if (d.market !== market) return;
|
|
1671
|
+
const inner = d.depth;
|
|
1672
|
+
const r = merger.apply({
|
|
1673
|
+
kind: "snapshot",
|
|
1674
|
+
bids: inner.bids.map(([p, s]) => ({
|
|
1675
|
+
price: Number(p),
|
|
1676
|
+
size: Number(s)
|
|
1677
|
+
})),
|
|
1678
|
+
asks: inner.asks.map(([p, s]) => ({
|
|
1679
|
+
price: Number(p),
|
|
1680
|
+
size: Number(s)
|
|
1681
|
+
})),
|
|
1682
|
+
sequence: inner.updated_at,
|
|
1683
|
+
timestamp: inner.updated_at
|
|
1684
|
+
});
|
|
1685
|
+
if (!r.ok) return;
|
|
1686
|
+
lastMerged = {
|
|
1659
1687
|
bids: r.bids,
|
|
1660
1688
|
asks: r.asks,
|
|
1661
1689
|
timestamp: r.timestamp,
|
|
1662
1690
|
sequence: r.sequence
|
|
1663
1691
|
};
|
|
1664
|
-
|
|
1692
|
+
emitOverlayed();
|
|
1693
|
+
};
|
|
1694
|
+
const handleBbo = (b) => {
|
|
1695
|
+
if (b.market !== market) return;
|
|
1696
|
+
const bidPrice = Number(b.best_bid_price);
|
|
1697
|
+
const askPrice = Number(b.best_ask_price);
|
|
1698
|
+
const bidSize = Number(b.best_bid_size);
|
|
1699
|
+
const askSize = Number(b.best_ask_size);
|
|
1700
|
+
if (!Number.isFinite(bidPrice) || !Number.isFinite(askPrice)) return;
|
|
1701
|
+
lastTicker = {
|
|
1702
|
+
bid: { price: bidPrice, size: bidSize },
|
|
1703
|
+
ask: { price: askPrice, size: askSize },
|
|
1704
|
+
ts: b.updated_at
|
|
1705
|
+
};
|
|
1706
|
+
emitOverlayed();
|
|
1707
|
+
};
|
|
1708
|
+
const handlePayload = (text) => {
|
|
1709
|
+
let msg;
|
|
1710
|
+
try {
|
|
1711
|
+
msg = JSON.parse(text);
|
|
1712
|
+
} catch {
|
|
1713
|
+
return;
|
|
1714
|
+
}
|
|
1715
|
+
if (msg.id != null && !msg.method) return;
|
|
1716
|
+
if (!msg.data || !msg.method) return;
|
|
1717
|
+
if (msg.method === "depth.update") {
|
|
1718
|
+
handleDepth(msg.data);
|
|
1719
|
+
} else if (msg.method === "bbo.update") {
|
|
1720
|
+
handleBbo(msg.data);
|
|
1721
|
+
}
|
|
1665
1722
|
};
|
|
1666
1723
|
const onMessage = async (raw) => {
|
|
1667
1724
|
if (typeof raw === "string") {
|
|
@@ -1675,7 +1732,10 @@ function streamCoinexOrderbook(opts) {
|
|
|
1675
1732
|
url: opts.market === "spot" ? WS_SPOT5 : WS_FUTURES2,
|
|
1676
1733
|
onOpen: (sock) => {
|
|
1677
1734
|
merger.reset();
|
|
1678
|
-
|
|
1735
|
+
lastMerged = null;
|
|
1736
|
+
lastTicker = null;
|
|
1737
|
+
sock.send(subscribeDepth);
|
|
1738
|
+
sock.send(subscribeBbo);
|
|
1679
1739
|
},
|
|
1680
1740
|
onMessage
|
|
1681
1741
|
// Native WS ping/pong frames keep the connection alive — no app-level ping.
|
|
@@ -1687,6 +1747,32 @@ function streamCoinexOrderbook(opts) {
|
|
|
1687
1747
|
ws.connect().catch((e) => stream.emit("error", e));
|
|
1688
1748
|
return stream;
|
|
1689
1749
|
}
|
|
1750
|
+
function overlayAsk2(asks, top) {
|
|
1751
|
+
if (!(top.size > 0)) return asks;
|
|
1752
|
+
let i = 0;
|
|
1753
|
+
for (; i < asks.length; i++) {
|
|
1754
|
+
const level = asks[i];
|
|
1755
|
+
if (!level || level.price >= top.price) break;
|
|
1756
|
+
}
|
|
1757
|
+
const at = asks[i];
|
|
1758
|
+
if (at && at.price === top.price) {
|
|
1759
|
+
return [{ price: top.price, size: top.size }, ...asks.slice(i + 1)];
|
|
1760
|
+
}
|
|
1761
|
+
return [{ price: top.price, size: top.size }, ...asks.slice(i)];
|
|
1762
|
+
}
|
|
1763
|
+
function overlayBid2(bids, top) {
|
|
1764
|
+
if (!(top.size > 0)) return bids;
|
|
1765
|
+
let i = 0;
|
|
1766
|
+
for (; i < bids.length; i++) {
|
|
1767
|
+
const level = bids[i];
|
|
1768
|
+
if (!level || level.price <= top.price) break;
|
|
1769
|
+
}
|
|
1770
|
+
const at = bids[i];
|
|
1771
|
+
if (at && at.price === top.price) {
|
|
1772
|
+
return [{ price: top.price, size: top.size }, ...bids.slice(i + 1)];
|
|
1773
|
+
}
|
|
1774
|
+
return [{ price: top.price, size: top.size }, ...bids.slice(i)];
|
|
1775
|
+
}
|
|
1690
1776
|
|
|
1691
1777
|
// src/exchanges/coinex/index.ts
|
|
1692
1778
|
var CoinexClient = class {
|