diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..bce9986 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,56 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node: [20, 22] + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + + # The CLI depends on the @0xarchive/sdk release named in package.json. A + # CLI release can land in this repo before that SDK version reaches npm. + # In that window this step installs the newest published SDK for this run + # only and restores package.json afterwards. The CLI type-checks against + # either (it reads the newer SDK resources through its own interfaces), + # and the tests stub the SDK surface these commands call. Once the floor + # version is on npm, the first branch runs and nothing is substituted. + - name: Install dependencies + run: | + floor="$(node -p "require('./package.json').dependencies['@0xarchive/sdk']")" + if npm view "@0xarchive/sdk@${floor}" version > /dev/null 2>&1; then + npm install --no-audit --no-fund + else + latest="$(npm view @0xarchive/sdk version)" + echo "::warning::@0xarchive/sdk ${floor} is not published yet; installing ${latest} for this run only." + npm pkg set "dependencies.@0xarchive/sdk=${latest}" + npm install --no-audit --no-fund + git checkout -- package.json + fi + npm ls @0xarchive/sdk || true + + - name: Typecheck + run: npm run typecheck + + - name: Test + run: npm test + + - name: Build + run: npm run build + + - name: Package contents + run: npm run check:pack diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b05cf4..9a650d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,25 @@ # Changelog -## Unreleased +## 1.10.0 - 2026-09-28 ### Added +- Lighter on Robinhood Chain, the second Lighter deployment, as `--exchange rh-lighter` on every shared market-data command that Lighter mainnet supports: instruments, order book and order book history, trades (canonical range and preliminary recent tier), candles, funding, open interest, liquidations, prices, summary, freshness, and `auth test`. It is USDG-quoted with 84 markets (57 perp, 27 spot); perps are uppercase (`BTC`) and spot markets are dashed (`AAPL-USDG`). Trades and liquidations are served from 2026-06-26 20:10:26 UTC, the venue's first trade; order book, open interest, and funding from 2026-08-22 18:43 UTC; candles from 2026-06-26 once they are enabled for this deployment. It has no L3. +- Live Robinhood Chain streams: `oxa stream orderbook --exchange rh-lighter` and `oxa stream trades --exchange rh-lighter`, and `oxa stream subscribe` accepts `rh_lighter_orderbook`, `rh_lighter_trades`, `rh_lighter_open_interest`, and `rh_lighter_funding`. Messages have the same shapes as the `lighter_*` live channels, `--interval-ms` (100 to 5000) works on `rh_lighter_orderbook`, and drop notices on `rh_lighter_*` channels are warnings, as on Lighter mainnet. They are served on `wss://api.0xarchive.io/ws`, the CLI default. `rh_lighter_candles` is replay-only and is rejected before a socket opens. +- Account positions, `oxa positions ...`, on `hyperliquid`, `hip3`, `lighter`, and `rh-lighter`: `get` (latest snapshot, or as of `--timestamp`), `history` (hourly snapshots), `changes` (the change log), `market` (every open position in one market, with `--side`, `--min-value`, and `--include-system` on Lighter), `summary` (long/short positioning now or hourly), and `all` (every open position at one hour). Hyperliquid and HIP-3 add `account` and `account-history`. Hyperliquid and HIP-3 are keyed by `--address`; Lighter by `--account `. JSON output includes the response `meta` (as-of time, snapshot, source, quality, staleness, and finalization fields). +- `oxa accounts by-l1 --l1-address 0x...` lists the Lighter mainnet account indices owned by an L1 address. - `--cursor` on `oxa orders flow` and `oxa hip4 orders flow`: a resume point in Unix ms, and the API starts the response at the first bucket that opens after it. The API does not return `nextCursor` on order flow yet: it arrives with an API switch, and until then `nextCursor` in the order-flow output is `null`. +- A package-contents check (`npm run check:pack`) and a CI workflow that runs the typecheck, tests, build, and that check. ### Changed +- `oxa liquidations history` and `oxa liquidations volume` accept `--exchange lighter` and `--exchange rh-lighter`; they were previously refused. Lighter rows keep the trade's raw fields (`liquidationType`, `usdAmount`, both accounts, `rawJson`); Robinhood Chain rows from before live capture (2026-08-22) were backfilled from the venue's finalized export and carry `source` `bucket` with an empty `rawJson`. Lighter volume buckets carry a total and a count with no long/short split. `oxa liquidations user` stays Hyperliquid only. +- On Lighter ranges (both deployments), `oxa trades fetch` passes the response `meta` through, including the finalization fields (`meta.finalizedThrough`, and `meta.clampedTo` when the range was clamped to the watermark). Hyperliquid and HIP-3 trades output is unchanged. +- `oxa orders ...`, `oxa l4 ...`, and `oxa l2 ...` reject `--exchange lighter` and `--exchange rh-lighter` with a clear message before any request, instead of failing inside the command. - `--interval 1m` works on `oxa funding history`, `oxa oi history`, `oxa prices`, `oxa liquidations volume`, and the HIP-4 open interest and price commands. The API now serves 1-minute buckets on those routes. Funding, open interest, and prices used to refuse `1m` before sending the request. - `oxa orders flow` and `oxa hip4 orders flow` describe `--interval` as the bucket widths the API serves: `1m`, `5m`, `15m`, `1h` (default `1h`). The help used to list `30m`, `4h`, and `1d`, which the API refuses. +- The HIP-4 funding and liquidations refusals now list every exchange that serves those routes. +- Requires `@0xarchive/sdk` 1.12.0 or newer, the release with the Robinhood Chain client, the positions resources, and Lighter liquidations. ## 1.9.0 - 2026-09-25 diff --git a/README.md b/README.md index 7f521c6..792da40 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Terminal-first access to 0xArchive market data. -0xArchive is granular market data infrastructure for Hyperliquid and Lighter.xyz. HIP-3 builder perps, HIP-4 outcome markets, and Hyperliquid Spot live under the Hyperliquid namespace; the CLI exposes `--exchange hip3`, `--exchange hip4`, and the `oxa spot` group as convenience scopes for those markets. +0xArchive is granular market data infrastructure for two venues: Hyperliquid and Lighter. Lighter has two deployments: mainnet and Robinhood Chain. HIP-3 builder perps, HIP-4 outcome markets, and Hyperliquid Spot live under the Hyperliquid namespace; the CLI exposes `--exchange hip3`, `--exchange hip4`, and the `oxa spot` group as convenience scopes for those markets. Lighter mainnet is `--exchange lighter` and Lighter on Robinhood Chain is `--exchange rh-lighter`. Account positions (`oxa positions ...`) cover Hyperliquid, HIP-3, and both Lighter deployments. Use `oxa` when the job starts in a terminal, script, CI task, notebook setup step, Claude Code session, ChatGPT Codex session, or another coding-agent shell. Both coding agents can start here with `oxa auth test` and one market-data request before expanding into SDKs, MCP, skills, or Data Catalog exports. The command set covers order books, trades, candles, funding, open interest, liquidations, prices, freshness, Lighter L3, Hyperliquid/HIP-3 L4 routes, HIP-4 outcome markets, and Hyperliquid Spot. @@ -34,6 +34,12 @@ oxa orderbook get --exchange hyperliquid --symbol BTC --format pretty # Fetch recent Lighter trades oxa trades fetch --exchange lighter --symbol BTC --limit 50 +# Fetch the Lighter on Robinhood Chain order book for a tokenized stock (USDG-quoted) +oxa orderbook get --exchange rh-lighter --symbol AAPL-USDG --format pretty + +# Current positions of a Hyperliquid wallet +oxa positions get --exchange hyperliquid --address 0xYourWallet --format pretty + # Fetch Hyperliquid HIP-3 builder-perp candles oxa candles --exchange hip3 --symbol km:US500 \ --start 2026-02-28T00:00:00Z --end 2026-03-01T00:00:00Z --interval 1h @@ -74,7 +80,8 @@ oxa stream orderbook BTC --exchange lighter --duration-ms 10000 | Scope | Flag | Symbols | | --- | --- | --- | | Hyperliquid | `--exchange hyperliquid` | `BTC`, `ETH`, `SOL`, etc. | -| Lighter.xyz | `--exchange lighter` | `BTC`, `ETH`, etc. | +| Lighter (mainnet) | `--exchange lighter` | `BTC`, `ETH`, etc. | +| Lighter on Robinhood Chain | `--exchange rh-lighter` | USDG-quoted. Perps are uppercase (`BTC`, `ETH`); spot markets are dashed (`AAPL-USDG`). 84 markets: 57 perp, 27 spot. Trades and liquidations from 2026-06-26 20:10:26 UTC (venue launch); order book, OI, and funding from 2026-08-22 18:43 UTC; candles from 2026-06-26 once they are enabled for this deployment. No L3. | | Hyperliquid HIP-3 | `--exchange hip3` | `km:US500`, `xyz:XYZ100`, etc. Case-sensitive. | | Hyperliquid HIP-4 | `--exchange hip4` or `oxa hip4 ...` | Bare numerics: `0`, `1`, `42`. Legacy `#0` / `%230` forms still work. `mark_price` is implied probability (0..1), not USD. Per-side OI is available from 2026-05-02 at ~10s cadence; candles are available. No funding or liquidations. | | Hyperliquid Spot | `oxa spot ...` | Dashed canonical: `HYPE-USDC`, `PURR-USDC`. 326 pairs. Spot candles from 2025-03-22T10:50:22Z at `1m`/`5m`/`15m`/`30m`/`1h`/`4h`/`1d`/`1w`, max 1000 rows; trades from 2025-03-22; orderbook, L4, TWAP live from 2026-05-05. No funding, OI, or liquidations. | @@ -155,7 +162,9 @@ oxa trades fetch --exchange --symbol [options] | `--out` | No | Write JSON output to file | | `--format` | No | `json` (default) or `pretty` | -**Note:** Hyperliquid trades always require `--start` and `--end`. Lighter and HIP-3 can fetch recent trades without a range. +**Note:** Hyperliquid trades always require `--start` and `--end`. Lighter (both deployments) and HIP-3 can fetch recent trades without a range. + +On both Lighter deployments, a ranged request returns canonical trades only, up to a finalization watermark that runs about a day behind: the end of the range is clamped to it, and the JSON output carries `meta.finalizedThrough` (and `meta.clampedTo` when the range was clamped) when the SDK returns them. Without a range, the command returns the recent tier, which is preliminary until the watermark passes it. ### `oxa candles` @@ -177,7 +186,7 @@ oxa candles --exchange --symbol --start