@0xarchive/sdk 1.2.0 → 1.3.0

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/index.js CHANGED
@@ -39,6 +39,8 @@ __export(index_exports, {
39
39
  InstrumentResponseSchema: () => InstrumentResponseSchema,
40
40
  InstrumentSchema: () => InstrumentSchema,
41
41
  InstrumentTypeSchema: () => InstrumentTypeSchema,
42
+ L2OrderBookResource: () => L2OrderBookResource,
43
+ L4OrderBookReconstructor: () => L4OrderBookReconstructor,
42
44
  LighterClient: () => LighterClient,
43
45
  LiquidationArrayResponseSchema: () => LiquidationArrayResponseSchema,
44
46
  LiquidationSchema: () => LiquidationSchema,
@@ -1789,6 +1791,51 @@ var L4OrderBookResource = class {
1789
1791
  }
1790
1792
  };
1791
1793
 
1794
+ // src/resources/l2-orderbook.ts
1795
+ var L2OrderBookResource = class {
1796
+ constructor(http, basePath = "/v1", coinTransform = (c) => c.toUpperCase()) {
1797
+ this.http = http;
1798
+ this.basePath = basePath;
1799
+ this.coinTransform = coinTransform;
1800
+ }
1801
+ /** Get full-depth L2 order book snapshot. */
1802
+ async get(symbol, params) {
1803
+ const coin = this.coinTransform(symbol);
1804
+ const query = {};
1805
+ if (params?.timestamp != null) query.timestamp = params.timestamp;
1806
+ if (params?.depth != null) query.depth = params.depth;
1807
+ const resp = await this.http.get(
1808
+ `${this.basePath}/orderbook/${encodeURIComponent(coin)}/l2`,
1809
+ query
1810
+ );
1811
+ return resp.data;
1812
+ }
1813
+ /** Get paginated L2 full-depth history. */
1814
+ async history(symbol, params) {
1815
+ const coin = this.coinTransform(symbol);
1816
+ const resp = await this.http.get(
1817
+ `${this.basePath}/orderbook/${encodeURIComponent(coin)}/l2/history`,
1818
+ params
1819
+ );
1820
+ return {
1821
+ data: resp.data,
1822
+ nextCursor: resp.meta?.next_cursor ?? void 0
1823
+ };
1824
+ }
1825
+ /** Get tick-level L2 order book diffs. */
1826
+ async diffs(symbol, params) {
1827
+ const coin = this.coinTransform(symbol);
1828
+ const resp = await this.http.get(
1829
+ `${this.basePath}/orderbook/${encodeURIComponent(coin)}/l2/diffs`,
1830
+ params
1831
+ );
1832
+ return {
1833
+ data: resp.data,
1834
+ nextCursor: resp.meta?.next_cursor ?? void 0
1835
+ };
1836
+ }
1837
+ };
1838
+
1792
1839
  // src/resources/l3-orderbook.ts
1793
1840
  var L3OrderBookResource = class {
1794
1841
  constructor(http, basePath = "/v1", coinTransform = (c) => c.toUpperCase()) {
@@ -1864,6 +1911,10 @@ var HyperliquidClient = class {
1864
1911
  * L4 order book (snapshots, diffs, history)
1865
1912
  */
1866
1913
  l4Orderbook;
1914
+ /**
1915
+ * L2 full-depth order book (derived from L4)
1916
+ */
1917
+ l2Orderbook;
1867
1918
  /**
1868
1919
  * HIP-3 builder-deployed perpetuals (February 2026+)
1869
1920
  */
@@ -1881,6 +1932,7 @@ var HyperliquidClient = class {
1881
1932
  this.liquidations = new LiquidationsResource(http, basePath);
1882
1933
  this.orders = new OrdersResource(http, basePath);
1883
1934
  this.l4Orderbook = new L4OrderBookResource(http, basePath);
1935
+ this.l2Orderbook = new L2OrderBookResource(http, basePath);
1884
1936
  this.hip3 = new Hip3Client(http);
1885
1937
  }
1886
1938
  /**
@@ -1967,6 +2019,10 @@ var Hip3Client = class {
1967
2019
  * L4 order book (snapshots, diffs, history)
1968
2020
  */
1969
2021
  l4Orderbook;
2022
+ /**
2023
+ * L2 full-depth order book (derived from L4)
2024
+ */
2025
+ l2Orderbook;
1970
2026
  http;
1971
2027
  constructor(http) {
1972
2028
  this.http = http;
@@ -1981,6 +2037,7 @@ var Hip3Client = class {
1981
2037
  this.liquidations = new LiquidationsResource(http, basePath, coinTransform);
1982
2038
  this.orders = new OrdersResource(http, basePath, coinTransform);
1983
2039
  this.l4Orderbook = new L4OrderBookResource(http, basePath, coinTransform);
2040
+ this.l2Orderbook = new L2OrderBookResource(http, basePath, coinTransform);
1984
2041
  }
1985
2042
  /**
1986
2043
  * Get per-symbol data freshness across all data types
@@ -2860,6 +2917,136 @@ var OxArchiveWs = class {
2860
2917
  }
2861
2918
  }
2862
2919
  };
2920
+
2921
+ // src/l4-reconstructor.ts
2922
+ var L4OrderBookReconstructor = class {
2923
+ orders = /* @__PURE__ */ new Map();
2924
+ bidPrices = /* @__PURE__ */ new Map();
2925
+ askPrices = /* @__PURE__ */ new Map();
2926
+ /** Initialize from an L4 checkpoint. */
2927
+ loadCheckpoint(checkpoint) {
2928
+ this.orders.clear();
2929
+ this.bidPrices.clear();
2930
+ this.askPrices.clear();
2931
+ for (const order of [...checkpoint.bids, ...checkpoint.asks]) {
2932
+ const oid = order.oid;
2933
+ const price = Number(order.price);
2934
+ const size = Number(order.size);
2935
+ const side = order.side;
2936
+ this.orders.set(oid, {
2937
+ oid,
2938
+ userAddress: order.user_address ?? order.userAddress ?? "",
2939
+ side,
2940
+ price,
2941
+ size
2942
+ });
2943
+ const priceMap = side === "B" ? this.bidPrices : this.askPrices;
2944
+ if (!priceMap.has(price)) priceMap.set(price, /* @__PURE__ */ new Set());
2945
+ priceMap.get(price).add(oid);
2946
+ }
2947
+ }
2948
+ /** Apply a single L4 diff with matching engine. */
2949
+ applyDiff(diff, nonRestingOids) {
2950
+ const dt = diff.diff_type ?? diff.diffType;
2951
+ const oid = diff.oid;
2952
+ if (dt === "new") {
2953
+ if (nonRestingOids?.has(oid)) return;
2954
+ const newSize = diff.new_size ?? diff.newSize;
2955
+ if (newSize == null || newSize <= 0) return;
2956
+ const { side, price } = diff;
2957
+ const sz = newSize;
2958
+ if (side === "B") {
2959
+ for (const [askPx, oids] of this.askPrices) {
2960
+ if (askPx <= price) {
2961
+ for (const crossedOid of oids) this.orders.delete(crossedOid);
2962
+ this.askPrices.delete(askPx);
2963
+ }
2964
+ }
2965
+ } else {
2966
+ for (const [bidPx, oids] of this.bidPrices) {
2967
+ if (bidPx >= price) {
2968
+ for (const crossedOid of oids) this.orders.delete(crossedOid);
2969
+ this.bidPrices.delete(bidPx);
2970
+ }
2971
+ }
2972
+ }
2973
+ this.orders.set(oid, {
2974
+ oid,
2975
+ userAddress: diff.user_address ?? diff.userAddress ?? "",
2976
+ side,
2977
+ price,
2978
+ size: sz
2979
+ });
2980
+ const priceMap = side === "B" ? this.bidPrices : this.askPrices;
2981
+ if (!priceMap.has(price)) priceMap.set(price, /* @__PURE__ */ new Set());
2982
+ priceMap.get(price).add(oid);
2983
+ } else if (dt === "update") {
2984
+ const order = this.orders.get(oid);
2985
+ const updSize = diff.new_size ?? diff.newSize;
2986
+ if (order && updSize != null) {
2987
+ order.size = updSize;
2988
+ }
2989
+ } else if (dt === "remove") {
2990
+ const order = this.orders.get(oid);
2991
+ if (order) {
2992
+ this.orders.delete(oid);
2993
+ const priceMap = order.side === "B" ? this.bidPrices : this.askPrices;
2994
+ const oids = priceMap.get(order.price);
2995
+ if (oids) {
2996
+ oids.delete(oid);
2997
+ if (oids.size === 0) priceMap.delete(order.price);
2998
+ }
2999
+ }
3000
+ }
3001
+ }
3002
+ /** Return bids sorted by price descending. */
3003
+ bids() {
3004
+ return [...this.orders.values()].filter((o) => o.side === "B" && o.size > 0).sort((a, b) => b.price - a.price);
3005
+ }
3006
+ /** Return asks sorted by price ascending. */
3007
+ asks() {
3008
+ return [...this.orders.values()].filter((o) => o.side === "A" && o.size > 0).sort((a, b) => a.price - b.price);
3009
+ }
3010
+ bestBid() {
3011
+ const b = this.bids();
3012
+ return b.length > 0 ? b[0].price : null;
3013
+ }
3014
+ bestAsk() {
3015
+ const a = this.asks();
3016
+ return a.length > 0 ? a[0].price : null;
3017
+ }
3018
+ /** Check if the book is crossed. Should be false after correct reconstruction. */
3019
+ isCrossed() {
3020
+ const bb = this.bestBid();
3021
+ const ba = this.bestAsk();
3022
+ return bb != null && ba != null && bb >= ba;
3023
+ }
3024
+ get bidCount() {
3025
+ return [...this.orders.values()].filter((o) => o.side === "B" && o.size > 0).length;
3026
+ }
3027
+ get askCount() {
3028
+ return [...this.orders.values()].filter((o) => o.side === "A" && o.size > 0).length;
3029
+ }
3030
+ /** Aggregate L4 orders into L2 price levels. */
3031
+ deriveL2() {
3032
+ const bidAgg = /* @__PURE__ */ new Map();
3033
+ const askAgg = /* @__PURE__ */ new Map();
3034
+ for (const o of this.orders.values()) {
3035
+ if (o.size <= 0) continue;
3036
+ const agg = o.side === "B" ? bidAgg : askAgg;
3037
+ const existing = agg.get(o.price);
3038
+ if (existing) {
3039
+ existing.sz += o.size;
3040
+ existing.n += 1;
3041
+ } else {
3042
+ agg.set(o.price, { sz: o.size, n: 1 });
3043
+ }
3044
+ }
3045
+ const bids = [...bidAgg.entries()].sort(([a], [b]) => b - a).map(([px, v]) => ({ px, sz: v.sz, n: v.n }));
3046
+ const asks = [...askAgg.entries()].sort(([a], [b]) => a - b).map(([px, v]) => ({ px, sz: v.sz, n: v.n }));
3047
+ return { bids, asks };
3048
+ }
3049
+ };
2863
3050
  // Annotate the CommonJS export names for ESM import in node:
2864
3051
  0 && (module.exports = {
2865
3052
  ApiMetaSchema,
@@ -2881,6 +3068,8 @@ var OxArchiveWs = class {
2881
3068
  InstrumentResponseSchema,
2882
3069
  InstrumentSchema,
2883
3070
  InstrumentTypeSchema,
3071
+ L2OrderBookResource,
3072
+ L4OrderBookReconstructor,
2884
3073
  LighterClient,
2885
3074
  LiquidationArrayResponseSchema,
2886
3075
  LiquidationSchema,