LI.FI Perps SDK is a TypeScript SDK for trading perpetuals across multiple DEXes through one unified interface. This repository is the pnpm + Changesets monorepo that builds and publishes it.
Using the SDK? Start with the @lifi/perps-sdk package README for installation, quick start, and the WebSocket API, or read the full documentation. The rest of this page is for working on the repository.
Published packages live under packages/. @lifi/perps-types sits at the base with zero dependencies; the core @lifi/perps-sdk depends on it; each provider plugin depends on the types directly and takes the core SDK as a peer dependency.
| Package | Install for | Description |
|---|---|---|
@lifi/perps-sdk |
every project | Core SDK — PerpsClient, service functions, PerpsWsClient WebSocket client |
@lifi/perps-sdk-provider-hyperliquid |
Hyperliquid | Hyperliquid provider plugin |
@lifi/perps-sdk-provider-lighter |
Lighter | Lighter provider plugin |
@lifi/perps-sdk-provider-ondo |
Ondo | Ondo provider plugin |
@lifi/perps-types |
(transitive) | Shared types; re-exported from @lifi/perps-sdk |
pnpm workspace — Node >=24, pnpm 11 (pinned via packageManager). From the repository root:
| Command | Does |
|---|---|
pnpm install |
Install workspace dependencies |
pnpm build |
Build every package (CJS + ESM + types) |
pnpm test |
Run all package tests (vitest) |
pnpm test:unit |
Unit tests only (*.unit.spec.ts) |
pnpm test:cov |
Tests with coverage |
pnpm check |
Biome lint/format check |
pnpm check:write |
Biome auto-fix |
pnpm check:write:unsafe |
Biome auto-fix, including unsafe fixes |
pnpm check:types |
TypeScript type checking across packages |
pnpm check:types:spec |
TypeScript type checking for *.spec.ts files (excluded from check:types) |
pnpm check:circular-deps |
madge circular-dependency check |
pnpm knip:check |
Report unused files, deps, and exports |
pnpm knip:write |
Apply the knip fixes |
pnpm clean |
Delete the build output of every package |
pnpm clean:modules |
Delete every node_modules directory |
pnpm build for @lifi/perps-sdk-provider-lighter also generates the Go WASM runtime initializer and copies the WASM signer into dist/. That package has one more script, pnpm --filter @lifi/perps-sdk-provider-lighter test:consumers, which checks the package against consumer bundlers.
Husky runs three hooks after pnpm install:
| Hook | Runs |
|---|---|
pre-commit |
scripts/check-no-local-links.sh, then pnpm pre-commit (check, check:types, check:types:spec, check:circular-deps, knip:check) |
commit-msg |
commitlint with the Conventional Commits config |
pre-push |
test:unit in each package, one package at a time |
CI (.github/workflows/checks.yaml) runs check, build, check:types, check:types:spec, check:circular-deps, knip:check, and the full test script of each package.
Releases are automated with Changesets. You never edit versions or run npm publish by hand — you describe each change in a changeset, and CI (.github/workflows/publish.yaml) versions and publishes from main.
After a change that affects a published package, add a changeset:
pnpm changesetIt asks which packages changed and the bump level for each, then writes a markdown file under .changeset/. Commit that file with your PR. A changeset records exactly two things:
| Field | Controls |
|---|---|
package + patch / minor / major |
the semver bump magnitude |
| summary | the changelog entry |
Choose the bump by consumer impact: patch for fixes, minor for backward-compatible additions, major for breaking changes.
A PR that touches no published code (CI, examples/, root config) needs no release — record that explicitly with an empty changeset so the intent is visible:
pnpm changeset --empty- Merge your PR (with its changeset) to
main. - CI opens or refreshes a
chore: version packagesPR that consumes all pending changesets, bumps versions, and updates changelogs. - Merge that PR → CI publishes the bumped packages to npm (OIDC trusted publishing) and creates GitHub releases.
The bump level never selects a channel — the channel is whole-repo state, not a per-changeset field.
| Channel | npm dist-tag | How |
|---|---|---|
| Stable | latest |
default; merge changesets as above |
| Preview | preview |
label a PR release-preview → publishes a throwaway 0.0.0-preview-<sha> for each package that has a changeset, then comments the install command on the PR and removes the label |
| Alpha / Beta | alpha / beta |
enter pre-release mode (below) |
For a sustained pre-release line, enter pre mode on main:
pnpm changeset pre enter beta # commit the generated .changeset/pre.json
# every release from main is now X.Y.Z-beta.N on the `beta` dist-tag
pnpm changeset pre exit # commit the deletion to return to stableWhile in pre mode, authors still write ordinary changesets — pre mode applies the -beta.N suffix to all of them. Consumers opt in with npm i @lifi/perps-sdk@beta.
Example scripts in examples/. Each script uses a placeholder apiKey, and agent-trading.ts uses a placeholder wallet client. Replace them before you run a script.
Scripts:
| Script | What it shows |
|---|---|
market-data.ts |
Fetching markets, assets, prices, orderbook, OHLCV |
account-data.ts |
Account state, positions, orders, fills |
agent-trading.ts |
Full setup flow + placing and cancelling orders |
error-handling.ts |
Handling PerpsError codes and retries |
custom-storage.ts |
Plugging in a custom credential store |
websocket-subscriptions.ts |
WebSocket prices, orderbook, multi-listener dedup, status |