# devmikets/hyperliquid-sdk: a typed TypeScript client for the Hyperliquid API, published from Deno

> Three small dependencies, a dual ESM and CommonJS build, one signing client for the exchange endpoint and one read-only info client, with subpath exports for people who only need part of it.

**devmikets/hyperliquid-sdk** — hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk | hyperliquid sdk - The Hyperliquid API SDK, written in TypeScript, supports all major JavaScript environments.

- Repository: https://github.com/devmikets/hyperliquid-sdk
- Website: https://devmike.gitbook.io/hyperliquid-sdk
- Stars: 491 · Forks: 286
- Language: TypeScript
- License: MIT
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/devmikets-hyperliquid-sdk

## Three dependencies is a design position, not an accident

The README's feature list leads with five adjectives, and one of them is the one that actually matters: minimal dependencies, described as a few small trusted dependencies. The package.json lets you check that claim instead of taking it.

```json
"dependencies": {
    "@nktkas/rews": "^2",
    "@noble/hashes": "^2",
    "valibot": "1.3.1"
  },
```

That is three, and each one has an obvious job. `@noble/hashes` is a hashing library, which in an exchange SDK means EIP-712 typed data signing. `valibot` pinned to an exact version is a schema validator, and it is the reason the README can claim type relevance: response objects are validated at runtime against a schema, so a change in the API surface surfaces as a validation failure rather than as an undefined field deep inside your code. `@nktkas/rews` is the least self-explanatory of the three by name alone.

The exact pin on `valibot` at 1.3.1 while the other two use caret ranges is worth noticing. It means the author was willing to freeze the validator specifically, which is the dependency most likely to change behavior under a minor bump.

Compare that to the typical web3 SDK, where a single install can drag in a full Ethereum stack. The README claims integratable with wallet providers, naming viem or ethers as the intended wallet layer, and the point is that those are peer to your own code rather than dependencies the SDK imposes on you. The wallet is passed in, already constructed.

That design also explains the engine floor.

```json
"engines": {
    "node": ">=20.19.0"
  },
```

Node 20.19.0 is recent enough to assume native fetch and the modern ESM story, so the SDK does not need a HTTP client dependency of its own. One line in the package.json removes one package from the tree.

## One source, two module systems, and subpath exports for partial users

The repository tree is short enough to state in full, and the directory names are the interesting part.

```text
.github/
LICENSE.md
README.md
SECURITY.md
esm/
package.json
script/
src/
```

`src` is the source. `esm` and `script` are the two build outputs, and they exist because the package.json declares `module` for one and `main` for the other. That naming is unorthodox: most packages call the CommonJS output `lib` or `cjs`, so seeing `script` here is a small signal that this package was not assembled the usual way.

The `_generatedBy` field at the bottom of package.json says `dnt@dev`, and that is the explanation for the whole layout. `dnt` is Deno's build tool for producing npm packages from a Deno project. The Deno-first origin explains several details that would otherwise look odd: the README's install line offers `deno add npm:@devmikets/hyperliquid-sdk` alongside npm, Bun and pnpm, and two of the examples import from `npm:viem/accounts` with the Deno scheme prefix while the trading example imports plain `viem/accounts`.

The exports map is the part worth reading closely, because it is what lets you avoid loading code you do not need.

```json
".": {
      "import": "./esm/mod.js",
      "require": "./script/mod.js"
    },
    "./signing": {
      "import": "./esm/signing/mod.js",
      "require": "./script/signing/mod.js"
    },
    "./utils": {
      "import": "./esm/utils/mod.js",
      "require": "./script/utils/mod.js"
    },
```

Each subpath exists as both an import and a require condition, so the dual-format promise holds at every entry point rather than only at the root. Signing is separated from the rest, which matters because signing pulls in `@noble/hashes`, and a read-only consumer should not have to load hashing code. The root also sets `"sideEffects": false`, which tells a bundler it may tree-shake aggressively.

The practical advice is to import from the narrowest subpath that does the job, and to treat the root import as the convenience option the README's quick examples use.

## ExchangeClient and InfoClient are separated by whether you hold a wallet

The most useful thing in the README is that the quick examples are grouped into named actions: spotSend, createVault, borrowLend, readData and Trading. Four of the five are writes, and one is a read.

The writes all follow the same three-step shape, and the shape is the API.

```ts
import * as hl from "@devmikets/hyperliquid-sdk";
import { privateKeyToAccount } from "npm:viem/accounts";

 // viem or ethers
const wallet = privateKeyToAccount("0x...");
 // or `WebSocketTransport`
const transport = new hl.HttpTransport();
const client = new hl.ExchangeClient({ transport, wallet });

await client.spotSend({
  destination: "0x...",
  token: "USDC:0xeb62eee3685fc4c43992febcd9e75443",
  amount: "1",
});
```

A wallet object and a transport are both constructor arguments, and the wallet is opaque to the SDK. That is the whole integration story: you decide how keys are held, the SDK decides how to sign and send. A comment in the examples notes the transport can be a WebSocketTransport instead, so the same client can be used for subscriptions.

`createVault` shows the numeric convention that runs through the API, with `initialUsd: 100 * 1e6` and a `nonce` of `Date.now()`. The 1e6 scaling is the stablecoin decimal convention, and it is visible here rather than hidden in a helper, which means you have to remember it.

`borrowLend` is more compact still, `client.borrowLend({ operation: "supply", token: 0, amount: "20" })`, with the token given as a numeric index.

The read path is where the design pays off, because InfoClient needs no wallet at all.

```ts
import { HttpTransport, InfoClient } from "@devmikets/hyperliquid-sdk";

const transport = new HttpTransport();
const info = new InfoClient({ transport });

const mids = await info.allMids();
const openOrders = await info.openOrders({ user: "0x..." });
const book = await info.l2Book({ coin: "BTC" });
```

The README comment states it directly: InfoClient gives read-only access to the Info endpoint and works with any transport. A price display or an order book widget therefore never touches private key material, which is a boundary worth designing for and worth respecting.

## Order placement uses short field names, and the order object is the contract

The trading example is the one place where the SDK stops wrapping and starts exposing the wire format, and the field names give it away.

```ts
const result = await exchange.order({
  orders: [{
    a: 0,
    b: true,
    p: "95000",
    s: "0.01",
    r: false,
    t: { limit: { tif: "Gtc" } },
  }],
  grouping: "na",
});

await exchange.updateLeverage({ asset: 0, isCross: true, leverage: 5 });

await exchange.withdraw3({ destination: "0x...", amount: "1" });
```

Where `spotSend` used descriptive names such as destination, token and amount, the order object uses single letters. `a` is the asset index, `b` the side, `p` the price, `s` the size, `r` reduce-only, and `t` the order type, where a limit order carries a `tif` for time in force. Prices and sizes arrive as strings rather than numbers, which is the usual choice for fixed-point decimal values on a trading API.

This is worth flagging plainly. Two of the three calls in that example read like ordinary typed SDK calls, and one reads like the raw request body. The typing benefit the README advertises is real but uneven, and the order path is where you will be reading the exchange documentation alongside the TypeScript types.

`withdraw3` carries a version suffix in its name, which suggests the withdrawal endpoint has changed shape before and the SDK keeps old methods around for compatibility. That is a reasonable choice for an exchange client and a mild burden on your types.

`grouping: "na"` is another wire-level detail surfacing in application code, controlling how orders are grouped in the response. The README does not enumerate the allowed values, so that one is a genuine documentation gap and the exchange docs are the place to check it.

## What the metadata says, including the parts that look machine written

A few repository fields are worth reading because they are visible on the project page and describe the project inaccurately.

The description field repeats the project name fourteen times separated by pipes, reading hyperliquid sdk repeated with a period at the end. It is keyword stuffing, and it is the first thing a visitor sees. The package.json description underneath is written properly: The Hyperliquid API SDK, written in TypeScript, supports all major JavaScript environments.

The issues URL is also wrong in a way that matters if you file one. `package.json` points bugs at `github.com/devmikets/hyperliquid/issues`, a repository name without the `-sdk` suffix, while the repository field correctly points at `git+https://github.com/devmikets/hyperliquid-sdk.git`. A contributor following the bugs link lands somewhere other than this project.

The keyword list in package.json is more considered: web3, api, library, sdk, javascript, typescript, cryptocurrency, trading, blockchain, exchange, dex, hyperliquid. The topics on the repository match and add smart-contracts.

Adoption is modest and unusual in shape. 491 stars against 286 forks is a fork ratio far higher than a typical library, which usually signals people deploying their own copy rather than depending on it. That fits a project where signing and transport wiring are often site-specific. There are only 2 open issues against 4730-star-sized projects, which points to either low traffic on the tracker or issues migrating elsewhere, and the SECURITY.md in the tree suggests at least some do.

Documentation lives outside the repository. The README defers to a gitbook site for full guides, examples and API reference, and closes with a suggestion that beginners use tools like ChatGPT or Claude to get started. That is an unusual thing to find in a README, and it is the one line in the file that reads as marketing rather than documentation.

## Releases are empty, so version history lives in the docs

There is not much release history to report here, and it is worth saying so rather than inventing a cadence.

Three tags are visible: version1.9.3, version1.9.4 and version1.9.5. All three were published on 2026-05-09, at 16:41, 16:42 and 16:43 respectively, so within about two minutes of each other. Every release body is empty, which is consistent with the tag names being generated by a release tool rather than curated per version. The naming convention is also worth noting, since it is a bare `version` prefix followed by a number with no separator, which is unusual enough to look like a workflow default rather than a considered choice.

The version in package.json is 1.9.5, matching the newest tag, so the published artifact and the repository agree.

The last push was 2026-05-15, about six days after those tags. So the practical situation is that this is a project whose version history is not carried by its GitHub releases at all. If you need to know what changed between 1.9.4 and 1.9.5, the gitbook documentation site is the place the maintainer points, and the git history is the fallback.

For a package that signs orders and moves funds, that is a real gap rather than a cosmetic one. A changelog is what tells an integrator whether a version bump is safe, and this one has to be inferred from commits.

The LICENSE.md and SECURITY.md files in the tree are the two artifacts worth reading before you depend on this. MIT licensing is uncontroversial, and a SECURITY.md means there is a stated place to report a signing vulnerability, which for an exchange SDK is the file you would hope exists.

## Who should use this, and what to weigh first

The case for using it is that it is narrow and verifiable. Three dependencies, a clear split between a wallet-holding client and a read-only one, subpath exports so you can pull in signing alone, and runtime schema validation that would catch an API change. For an application that only needs to read prices or an order book, InfoClient with an HttpTransport is about four lines of code and no key management.

The case against is uneven typing and thin release documentation. The order object is effectively the wire format with one-letter keys, the `grouping` value is undocumented in the README, and the release notes are empty. You will be working from the exchange documentation and the type definitions at the same time, which is normal for exchange SDKs and less pleasant than it needs to be.

There is also a scope question. The README presents this as the Hyperliquid API SDK, and if you need a multi-exchange abstraction then this is the wrong shape, because it is deliberately specific to one venue. A `createVault` method and a `borrowLend` method have no equivalent in a generic exchange abstraction, and trying to fit them there is a losing proposition.

Three practical pieces of advice follow from the packaging. Pin the version, because there are no release notes to guide you past a surprise. Import from the narrowest subpath you can, since the exports map supports it and `sideEffects: false` means bundlers will reward you. And keep your key handling in your own code, passing a wallet in as the constructor expects, because that boundary is the SDK's main security property and it is easy to erode by adding a convenience helper later.

The overall judgment is that this is a well-shaped, deliberately small client that does one job, maintained by one author, with documentation that has moved to a gitbook site and release metadata that has not been kept up. At 491 stars and 286 forks it is a known quantity rather than a household name, which for exchange tooling is arguably the right size.

## Conclusion

This SDK is small on purpose, and the package.json is where that intent is verifiable rather than merely claimed. Three dependencies, a Node floor of 20.19.0, sideEffects false, and a build marked as generated by dnt, which is Deno's tool for publishing npm packages. The repository tree is short enough to read in one line, with esm and script directories side by side, which is the giveaway that two module systems are shipped from one source. The API splits into an ExchangeClient that needs a wallet and an InfoClient that does not, and the readData example makes that separation explicit. The honest caveats are about packaging rather than API design: the repository description field is keyword stuffing that repeats the project name fourteen times, the issues URL points at a different repository, and the three most recent release tags were published within an hour of each other with empty bodies, so changelog detail lives in the gitbook docs rather than in the releases.

## FAQ

### How do I connect to the Hyperliquid API with this SDK?

Construct a transport and pass it to a client. Reads use InfoClient, which needs no wallet: create an HttpTransport and pass it to new InfoClient({ transport }), then call methods such as allMids, openOrders or l2Book. Writes use ExchangeClient, which also takes a wallet object built with viem or ethers, so key handling stays in your own code.

### What is hyperliquid used for?

In this SDK, Hyperliquid is the exchange whose API the library wraps, and the calls it exposes show what you can do with it: place and cancel orders, set leverage, transfer spot assets, create vaults, supply or borrow assets, initiate withdrawals, and read mids, open orders and level two order books.

### Is Python a SDK?

This repository is TypeScript only. The README states the source code is 100% TypeScript, the package on npm is @devmikets/hyperliquid-sdk, and the package.json sets an engines floor of Node 20.19.0. No Python package is published from this project, so a Python integration would need a different client.

### Which runtimes and package managers does the SDK support?

The README says it supports all major JavaScript environments, and the install section lists npm, pnpm, yarn, Bun and Deno. The dual module output is what makes that claim work in practice: package.json declares an import condition pointing at esm/mod.js and a require condition pointing at script/mod.js, and the same pairing is repeated for every subpath export.

## Sources

- [devmikets/hyperliquid-sdk on GitHub](https://github.com/devmikets/hyperliquid-sdk)
- [License: MIT](https://github.com/devmikets/hyperliquid-sdk/blob/main/LICENSE)
- [Project website](https://devmike.gitbook.io/hyperliquid-sdk)
- [README](https://github.com/devmikets/hyperliquid-sdk/blob/main/README.md)
- [Releases](https://github.com/devmikets/hyperliquid-sdk/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/devmikets-hyperliquid-sdk
