@xapy/orderbook 0.1.6 → 0.1.7
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 +57 -140
- package/dist/exchanges/coinex/index.cjs.map +1 -1
- package/dist/exchanges/coinex/index.d.cts +16 -10
- package/dist/exchanges/coinex/index.d.ts +16 -10
- package/dist/exchanges/coinex/index.js +57 -140
- package/dist/exchanges/coinex/index.js.map +1 -1
- package/dist/index.cjs +62 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -116
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1618,94 +1618,61 @@ async function fetchCoinexOrderbook(opts) {
|
|
|
1618
1618
|
}
|
|
1619
1619
|
|
|
1620
1620
|
// src/exchanges/coinex/ws.ts
|
|
1621
|
-
var WS_SPOT5 = "wss://socket.coinex.com/
|
|
1622
|
-
var WS_FUTURES2 = "wss://
|
|
1621
|
+
var WS_SPOT5 = "wss://socket.coinex.com/";
|
|
1622
|
+
var WS_FUTURES2 = "wss://perpetual.coinex.com/";
|
|
1623
1623
|
function streamCoinexOrderbook(opts) {
|
|
1624
1624
|
const market = toCoinexSymbol(opts.symbol);
|
|
1625
1625
|
const depth = opts.depth ?? 50;
|
|
1626
1626
|
const merger = new BookMerger();
|
|
1627
|
+
let seq = 0;
|
|
1627
1628
|
let ws = null;
|
|
1628
1629
|
const stream = new OrderbookStream(() => ws?.close());
|
|
1629
|
-
const
|
|
1630
|
+
const subscribePayload = JSON.stringify({
|
|
1630
1631
|
method: "depth.subscribe",
|
|
1631
|
-
params:
|
|
1632
|
-
// [market, limit, interval, diff_flag] — diff_flag=true → snapshots only
|
|
1633
|
-
// (CoinEx flips the sense of the flag in V2; our handler treats every
|
|
1634
|
-
// frame as a snapshot to stay correct under either reading).
|
|
1635
|
-
market_list: [[market, depth, "0", true]]
|
|
1636
|
-
},
|
|
1632
|
+
params: [market, depth, "0", true],
|
|
1637
1633
|
id: 1
|
|
1638
1634
|
});
|
|
1639
|
-
const
|
|
1640
|
-
|
|
1641
|
-
params: { market_list: [market] },
|
|
1642
|
-
id: 2
|
|
1643
|
-
});
|
|
1644
|
-
let lastMerged = null;
|
|
1645
|
-
let lastTicker = null;
|
|
1646
|
-
const emitOverlayed = () => {
|
|
1647
|
-
if (!lastMerged) return;
|
|
1648
|
-
let bids = lastMerged.bids;
|
|
1649
|
-
let asks = lastMerged.asks;
|
|
1650
|
-
let timestamp = lastMerged.timestamp;
|
|
1651
|
-
let sequence = lastMerged.sequence;
|
|
1652
|
-
if (lastTicker) {
|
|
1653
|
-
bids = overlayBid2(bids, lastTicker.bid);
|
|
1654
|
-
asks = overlayAsk2(asks, lastTicker.ask);
|
|
1655
|
-
if (lastTicker.ts > timestamp) {
|
|
1656
|
-
timestamp = lastTicker.ts;
|
|
1657
|
-
sequence = Math.max(sequence, lastTicker.ts);
|
|
1658
|
-
}
|
|
1659
|
-
}
|
|
1635
|
+
const pingPayload = () => JSON.stringify({ method: "server.ping", params: [], id: 11 });
|
|
1636
|
+
const emit = (r) => {
|
|
1660
1637
|
const book = {
|
|
1661
1638
|
exchange: "coinex",
|
|
1662
1639
|
symbol: fromCoinexSymbol(market),
|
|
1663
1640
|
market: opts.market,
|
|
1664
|
-
bids,
|
|
1665
|
-
asks,
|
|
1666
|
-
timestamp,
|
|
1667
|
-
sequence
|
|
1668
|
-
};
|
|
1669
|
-
stream.emit("update", book);
|
|
1670
|
-
};
|
|
1671
|
-
const handleDepth = (d) => {
|
|
1672
|
-
if (d.market !== market) return;
|
|
1673
|
-
const inner = d.depth;
|
|
1674
|
-
const r = merger.apply({
|
|
1675
|
-
kind: "snapshot",
|
|
1676
|
-
bids: inner.bids.map(([p, s]) => ({
|
|
1677
|
-
price: Number(p),
|
|
1678
|
-
size: Number(s)
|
|
1679
|
-
})),
|
|
1680
|
-
asks: inner.asks.map(([p, s]) => ({
|
|
1681
|
-
price: Number(p),
|
|
1682
|
-
size: Number(s)
|
|
1683
|
-
})),
|
|
1684
|
-
sequence: inner.updated_at,
|
|
1685
|
-
timestamp: inner.updated_at
|
|
1686
|
-
});
|
|
1687
|
-
if (!r.ok) return;
|
|
1688
|
-
lastMerged = {
|
|
1689
1641
|
bids: r.bids,
|
|
1690
1642
|
asks: r.asks,
|
|
1691
1643
|
timestamp: r.timestamp,
|
|
1692
1644
|
sequence: r.sequence
|
|
1693
1645
|
};
|
|
1694
|
-
|
|
1646
|
+
stream.emit("update", book);
|
|
1695
1647
|
};
|
|
1696
|
-
const
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
const
|
|
1700
|
-
const
|
|
1701
|
-
const
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1648
|
+
const handleDepthPush = (push) => {
|
|
1649
|
+
const [clean, payload, mkt] = push;
|
|
1650
|
+
if (mkt !== market) return;
|
|
1651
|
+
const bids = parseLevels(payload.bids);
|
|
1652
|
+
const asks = parseLevels(payload.asks);
|
|
1653
|
+
const event = clean ? {
|
|
1654
|
+
kind: "snapshot",
|
|
1655
|
+
bids,
|
|
1656
|
+
asks,
|
|
1657
|
+
sequence: ++seq,
|
|
1658
|
+
timestamp: payload.time
|
|
1659
|
+
} : {
|
|
1660
|
+
kind: "delta",
|
|
1661
|
+
bids,
|
|
1662
|
+
asks,
|
|
1663
|
+
sequence: ++seq,
|
|
1664
|
+
timestamp: payload.time
|
|
1707
1665
|
};
|
|
1708
|
-
|
|
1666
|
+
const r = merger.apply(event);
|
|
1667
|
+
if (r.ok) {
|
|
1668
|
+
emit(r);
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
if (r.reason === "no-snapshot") return;
|
|
1672
|
+
if (r.reason === "gap") {
|
|
1673
|
+
merger.reset();
|
|
1674
|
+
seq = 0;
|
|
1675
|
+
}
|
|
1709
1676
|
};
|
|
1710
1677
|
const handlePayload = (text) => {
|
|
1711
1678
|
let msg;
|
|
@@ -1715,32 +1682,31 @@ function streamCoinexOrderbook(opts) {
|
|
|
1715
1682
|
return;
|
|
1716
1683
|
}
|
|
1717
1684
|
if (msg.id != null && !msg.method) return;
|
|
1718
|
-
if (
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
}
|
|
1724
|
-
};
|
|
1725
|
-
const onMessage = async (raw) => {
|
|
1726
|
-
if (typeof raw === "string") {
|
|
1727
|
-
handlePayload(raw);
|
|
1685
|
+
if (msg.error) {
|
|
1686
|
+
stream.emit(
|
|
1687
|
+
"error",
|
|
1688
|
+
new Error(`coinex: ${msg.error.code} ${msg.error.message}`)
|
|
1689
|
+
);
|
|
1728
1690
|
return;
|
|
1729
1691
|
}
|
|
1730
|
-
|
|
1731
|
-
|
|
1692
|
+
if (msg.method === "depth.update" && Array.isArray(msg.params)) {
|
|
1693
|
+
handleDepthPush(msg.params);
|
|
1694
|
+
}
|
|
1695
|
+
};
|
|
1696
|
+
const onMessage = (raw) => {
|
|
1697
|
+
if (typeof raw !== "string") return;
|
|
1698
|
+
handlePayload(raw);
|
|
1732
1699
|
};
|
|
1733
1700
|
ws = new WSClient({
|
|
1734
1701
|
url: opts.market === "spot" ? WS_SPOT5 : WS_FUTURES2,
|
|
1735
1702
|
onOpen: (sock) => {
|
|
1736
1703
|
merger.reset();
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
sock.send(subscribeDepth);
|
|
1740
|
-
sock.send(subscribeBbo);
|
|
1704
|
+
seq = 0;
|
|
1705
|
+
sock.send(subscribePayload);
|
|
1741
1706
|
},
|
|
1742
|
-
onMessage
|
|
1743
|
-
|
|
1707
|
+
onMessage,
|
|
1708
|
+
pingIntervalMs: 25e3,
|
|
1709
|
+
pingPayload
|
|
1744
1710
|
});
|
|
1745
1711
|
ws.on("open", () => stream.emit("connected"));
|
|
1746
1712
|
ws.on("close", (r) => stream.emit("disconnected", r));
|
|
@@ -1749,31 +1715,11 @@ function streamCoinexOrderbook(opts) {
|
|
|
1749
1715
|
ws.connect().catch((e) => stream.emit("error", e));
|
|
1750
1716
|
return stream;
|
|
1751
1717
|
}
|
|
1752
|
-
function
|
|
1753
|
-
if (!
|
|
1754
|
-
|
|
1755
|
-
for (
|
|
1756
|
-
|
|
1757
|
-
if (!level || level.price >= top.price) break;
|
|
1758
|
-
}
|
|
1759
|
-
const at = asks[i];
|
|
1760
|
-
if (at && at.price === top.price) {
|
|
1761
|
-
return [{ price: top.price, size: top.size }, ...asks.slice(i + 1)];
|
|
1762
|
-
}
|
|
1763
|
-
return [{ price: top.price, size: top.size }, ...asks.slice(i)];
|
|
1764
|
-
}
|
|
1765
|
-
function overlayBid2(bids, top) {
|
|
1766
|
-
if (!(top.size > 0)) return bids;
|
|
1767
|
-
let i = 0;
|
|
1768
|
-
for (; i < bids.length; i++) {
|
|
1769
|
-
const level = bids[i];
|
|
1770
|
-
if (!level || level.price <= top.price) break;
|
|
1771
|
-
}
|
|
1772
|
-
const at = bids[i];
|
|
1773
|
-
if (at && at.price === top.price) {
|
|
1774
|
-
return [{ price: top.price, size: top.size }, ...bids.slice(i + 1)];
|
|
1775
|
-
}
|
|
1776
|
-
return [{ price: top.price, size: top.size }, ...bids.slice(i)];
|
|
1718
|
+
function parseLevels(rows) {
|
|
1719
|
+
if (!rows) return [];
|
|
1720
|
+
const out = [];
|
|
1721
|
+
for (const [p, s] of rows) out.push({ price: Number(p), size: Number(s) });
|
|
1722
|
+
return out;
|
|
1777
1723
|
}
|
|
1778
1724
|
|
|
1779
1725
|
// src/exchanges/coinex/index.ts
|
|
@@ -2471,8 +2417,8 @@ async function fetchKucoinOrderbook(opts) {
|
|
|
2471
2417
|
exchange: "kucoin",
|
|
2472
2418
|
symbol: fromKucoinSpotSymbol(symbol2),
|
|
2473
2419
|
market: "spot",
|
|
2474
|
-
bids:
|
|
2475
|
-
asks:
|
|
2420
|
+
bids: parseLevels2(res2.data.bids),
|
|
2421
|
+
asks: parseLevels2(res2.data.asks),
|
|
2476
2422
|
timestamp: res2.data.time,
|
|
2477
2423
|
sequence: Number(res2.data.sequence)
|
|
2478
2424
|
};
|
|
@@ -2491,13 +2437,13 @@ async function fetchKucoinOrderbook(opts) {
|
|
|
2491
2437
|
exchange: "kucoin",
|
|
2492
2438
|
symbol: fromKucoinFuturesSymbol(symbol),
|
|
2493
2439
|
market: "perpetual",
|
|
2494
|
-
bids:
|
|
2495
|
-
asks:
|
|
2440
|
+
bids: parseLevels2(res.data.bids),
|
|
2441
|
+
asks: parseLevels2(res.data.asks),
|
|
2496
2442
|
timestamp: res.data.ts,
|
|
2497
2443
|
sequence: res.data.sequence
|
|
2498
2444
|
};
|
|
2499
2445
|
}
|
|
2500
|
-
function
|
|
2446
|
+
function parseLevels2(rows) {
|
|
2501
2447
|
return rows.map(([p, s]) => ({ price: Number(p), size: Number(s) }));
|
|
2502
2448
|
}
|
|
2503
2449
|
|