Hyperliquid API TypeScript SDK

Unofficial Hyperliquid API SDK for all major JS
runtimes, written in TypeScript.
Features
- ๐๏ธ Typed: Source code is 100% TypeScript.
- ๐งช Tested: Good code coverage and type relevance.
- ๐ฆ Minimal dependencies: A few small trusted dependencies.
- ๐ Cross-Environment Support: Compatible with all major JS runtimes.
- ๐ง Integratable: Easy to use with wallet providers (viem or
ethers).
- ๐ Documented: JSDoc annotations with usage examples.
- ๐ฒ Tree-shaking friendly: Easily import only the API calls you use for minimal
bundle size.
Installation
Node.js 20+ (choose your package manager)
npm i @nktkas/hyperliquid
pnpm add @nktkas/hyperliquid
yarn add @nktkas/hyperliquid
Note for Node.js versions below 22
Node.js 22+ includes native WebSocket. For earlier versions using WebSocketTransport,
install ws package and pass the class:
import WebSocket from "ws";
import * as hl from "@nktkas/hyperliquid";
const transport = new hl.WebSocketTransport({
reconnect: {
WebSocket,
},
});
Deno 2.0+
deno add jsr:@nktkas/hyperliquid
Web
The SDK is fully browser-compatible; integrate it via CDN or bundle it with your application.
<script type="module">
import * as hl from "https://esm.sh/jsr/@nktkas/hyperliquid";
</script>
React Native
For React Native, you need to import polyfills before importing the SDK:
import "fast-text-encoding";
import "event-target-polyfill";
import * as hl from "@nktkas/hyperliquid";
Quick Start
CLI
The SDK includes a command-line interface for quick interactions with Hyperliquid API without writing code.
npx @nktkas/hyperliquid --help
import * as hl from "@nktkas/hyperliquid";
const infoClient = new hl.InfoClient({
transport: new hl.HttpTransport(),
});
const openOrders = await infoClient.openOrders({ user: "0x..." });
import * as hl from "@nktkas/hyperliquid";
const exchClient = new hl.ExchangeClient({
wallet: "0x...",
transport: new hl.HttpTransport(),
});
const result = await exchClient.order({
orders: [{
a: 0,
b: true,
p: "30000",
s: "0.1",
r: false,
t: {
limit: {
tif: "Gtc",
},
},
}],
grouping: "na",
});
import * as hl from "@nktkas/hyperliquid";
const subsClient = new hl.SubscriptionClient({
transport: new hl.WebSocketTransport(),
});
const sub = await subsClient.allMids((event) => {
console.log(event);
});
await sub.unsubscribe();
import * as hl from "@nktkas/hyperliquid";
const multiSignClient = new hl.MultiSignClient({
transport: new hl.HttpTransport(),
multiSigUser: "0x...",
signers: [
"0x...",
],
});
await multiSignClient.approveAgent({ agentAddress: "0x..." });
Usage
1) Initialize Transport
First, choose and configure your transport layer (more details in the Transports):
import * as hl from "@nktkas/hyperliquid";
const httpTransport = new hl.HttpTransport({ ... });
const wsTransport = new hl.WebSocketTransport({ ... });
2) Initialize Client
Next, initialize a client with the transport layer (more details in the Clients):
import * as hl from "@nktkas/hyperliquid";
const infoClient = new hl.InfoClient({
transport: new hl.HttpTransport(),
});
import * as hl from "@nktkas/hyperliquid";
import { createWalletClient, custom } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { ethers } from "ethers";
const transport = new hl.HttpTransport();
const pk = "0x...";
const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
const viemAccount = privateKeyToAccount("0x...");
const exchClient = new hl.ExchangeClient({ wallet: viemAccount, transport });
const ethersWallet = new ethers.Wallet("0x...");
const exchClient = new hl.ExchangeClient({ wallet: ethersWallet, transport });
const [account] = await window.ethereum.request({ method: "eth_requestAccounts" }) as `0x${string}`[];
const externalWallet = createWalletClient({ account, transport: custom(window.ethereum) });
const exchClient = new hl.ExchangeClient({ wallet: externalWallet, transport });
import * as hl from "@nktkas/hyperliquid";
const subsClient = new hl.SubscriptionClient({
transport: new hl.WebSocketTransport(),
});
import * as hl from "@nktkas/hyperliquid";
import { privateKeyToAccount } from "viem/accounts";
import { ethers } from "ethers";
const multiSignClient = new hl.MultiSignClient({
transport: new hl.HttpTransport(),
multiSigUser: "0x...",
signers: [
privateKeyToAccount("0x..."),
new ethers.Wallet("0x..."),
{
async signTypedData(params: {
domain: {
name: string;
version: string;
chainId: number;
verifyingContract: Hex;
};
types: {
[key: string]: {
name: string;
type: string;
}[];
};
primaryType: string;
message: Record<string, unknown>;
}): Promise<Hex> {
return "0x...";
},
},
"0x...",
],
});
3) Use Client
Finally, use client methods to interact with the Hyperliquid API (more details in the API Reference):
import * as hl from "@nktkas/hyperliquid";
const infoClient = new hl.InfoClient({
transport: new hl.HttpTransport(),
});
const l2Book = await infoClient.l2Book({ coin: "ETH" });
const clearinghouseState = await infoClient.clearinghouseState({ user: "0x..." });
const openOrders = await infoClient.openOrders({ user: "0x..." });
import * as hl from "@nktkas/hyperliquid";
const exchClient = new hl.ExchangeClient({
wallet: "0x...",
transport: new hl.HttpTransport(),
});
const result = await exchClient.order({
orders: [{
a: 0,
b: true,
p: "30000",
s: "0.1",
r: false,
t: {
limit: {
tif: "Gtc",
},
},
}],
grouping: "na",
});
const result = await exchClient.approveAgent({ agentAddress: "0x..." });
const result = await exchClient.withdraw3({ destination: "0x...", amount: "100" });
import * as hl from "@nktkas/hyperliquid";
const subsClient = new hl.SubscriptionClient({
transport: new hl.WebSocketTransport(),
});
await subsClient.l2Book({ coin: "ETH" }, (data) => {
console.log(data);
});
await subsClient.userFills({ user: "0x..." }, (data) => {
console.log(data);
});
await subsClient.candle({ coin: "ETH", interval: "1h" }, (data) => {
console.log(data);
});
import * as hl from "@nktkas/hyperliquid";
const multiSignClient = new hl.MultiSignClient({
transport: new hl.HttpTransport(),
multiSigUser: "0x...",
signers: [
"0x...",
],
});
API Reference
Clients
A client is an interface through which you can interact with the Hyperliquid API.
InfoClient
class InfoClient {
constructor(args: {
/** The transport used to connect to the Hyperliquid API. */
transport: HttpTransport | WebSocketTransport;
});
alignedQuoteTokenInfo(params: AlignedQuoteTokenInfoParameters): Promise<AlignedQuoteTokenInfoResponse>;
allMids(params?: AllMidsParameters): Promise<AllMidsResponse>;
allPerpMetas(): Promise<AllPerpMetasResponse>;
candleSnapshot(params: CandleSnapshotParameters): Promise<CandleSnapshotResponse>;
fundingHistory(params: FundingHistoryParameters): Promise<FundingHistoryResponse>;
l2Book(params: L2BookParameters): Promise<L2BookResponse>;
liquidatable(): Promise<LiquidatableResponse>;
marginTable(params: MarginTableParameters): Promise<MarginTableResponse>;
maxMarketOrderNtls(): Promise<MaxMarketOrderNtlsResponse>;
meta(params?: MetaParameters): Promise<MetaResponse>;
metaAndAssetCtxs(params?: MetaAndAssetCtxsParameters): Promise<MetaAndAssetCtxsResponse>;
perpDexLimits(params: PerpDexLimitsParameters): Promise<PerpDexLimitsResponse>;
perpDexs(): Promise<PerpDexsResponse>;
perpsAtOpenInterestCap(params?: PerpsAtOpenInterestCapParameters): Promise<PerpsAtOpenInterestCapResponse>;
predictedFundings(): Promise<PredictedFundingsResponse>;
recentTrades(params: RecentTradesParameters): Promise<RecentTradesResponse>;
spotMeta(): Promise<SpotMetaResponse>;
spotMetaAndAssetCtxs(): Promise<SpotMetaAndAssetCtxsResponse>;
activeAssetData(params: ActiveAssetDataParameters): Promise<ActiveAssetDataResponse>;
clearinghouseState(params: ClearinghouseStateParameters): Promise<ClearinghouseStateResponse>;
extraAgents(params: ExtraAgentsParameters): Promise<ExtraAgentsResponse>;
isVip(params: IsVipParameters): Promise<IsVipResponse>;
legalCheck(params: LegalCheckParameters): Promise<LegalCheckResponse>;
maxBuilderFee(params: MaxBuilderFeeParameters): Promise<MaxBuilderFeeResponse>;
portfolio(params: PortfolioParameters): Promise<PortfolioResponse>;
preTransferCheck(params: PreTransferCheckParameters): Promise<PreTransferCheckResponse>;
referral(params: ReferralParameters): Promise<ReferralResponse>;
spotClearinghouseState(params: SpotClearinghouseStateParameters): Promise<SpotClearinghouseStateResponse>;
subAccounts(params: SubAccountsParameters): Promise<SubAccountsResponse>;
subAccounts2(params: SubAccounts2Parameters): Promise<SubAccounts2Response>;
userDexAbstraction(params: UserDexAbstractionInfoParameters): Promise<UserDexAbstractionInfoResponse>;
userFees(params: UserFeesParameters): Promise<UserFeesResponse>;
userFunding(params: UserFundingParameters): Promise<UserFundingResponse>;
userNonFundingLedgerUpdates(
params: UserNonFundingLedgerUpdatesParameters,
): Promise<UserNonFundingLedgerUpdatesResponse>;
userRateLimit(params: UserRateLimitParameters): Promise<UserRateLimitResponse>;
userRole(params: UserRoleParameters): Promise<UserRoleResponse>;
userToMultiSigSigners(params: UserToMultiSigSignersParameters): Promise<UserToMultiSigSignersResponse>;
webData2(params: WebData2Parameters): Promise<WebData2Response>;
frontendOpenOrders(params: FrontendOpenOrdersParameters): Promise<FrontendOpenOrdersResponse>;
historicalOrders(params: HistoricalOrdersParameters): Promise<HistoricalOrdersResponse>;
openOrders(params: OpenOrdersParameters): Promise<OpenOrdersResponse>;
orderStatus(params: OrderStatusParameters): Promise<OrderStatusResponse>;
twapHistory(params: TwapHistoryParameters): Promise<TwapHistoryResponse>;
userFills(params: UserFillsParameters): Promise<UserFillsResponse>;
userFillsByTime(params: UserFillsByTimeParameters): Promise<UserFillsByTimeResponse>;
userTwapSliceFills(params: UserTwapSliceFillsParameters): Promise<UserTwapSliceFillsResponse>;
userTwapSliceFillsByTime(params: UserTwapSliceFillsByTimeParameters): Promise<UserTwapSliceFillsByTimeResponse>;
delegations(params: DelegationsParameters): Promise<DelegationsResponse>;
delegatorHistory(params: DelegatorHistoryParameters): Promise<DelegatorHistoryResponse>;
delegatorRewards(params: DelegatorRewardsParameters): Promise<DelegatorRewardsResponse>;
delegatorSummary(params: DelegatorSummaryParameters): Promise<DelegatorSummaryResponse>;
gossipRootIps(): Promise<GossipRootIpsResponse>;
validatorL1Votes(): Promise<ValidatorL1VotesResponse>;
validatorSummaries(): Promise<ValidatorSummariesResponse>;
leadingVaults(params: LeadingVaultsParameters): Promise<LeadingVaultsResponse>;
userVaultEquities(params: UserVaultEquitiesParameters): Promise<UserVaultEquitiesResponse>;
vaultDetails(params: VaultDetailsParameters): Promise<VaultDetailsResponse>;
vaultSummaries(): Promise<VaultSummariesResponse>;
perpDeployAuctionStatus(): Promise<PerpDeployAuctionStatusResponse>;
spotDeployState(params: SpotDeployStateParameters): Promise<SpotDeployStateResponse>;
spotPairDeployAuctionStatus(): Promise<SpotPairDeployAuctionStatusResponse>;
exchangeStatus(): Promise<ExchangeStatusResponse>;
blockDetails(params: BlockDetailsParameters): Promise<BlockDetailsResponse>;
txDetails(params: TxDetailsParameters): Promise<TxDetailsResponse>;
userDetails(params: UserDetailsParameters): Promise<UserDetailsResponse>;
tokenDetails(params: TokenDetailsParameters): Promise<TokenDetailsResponse>;
}
ExchangeClient
class ExchangeClient {
constructor(args: {
/** The transport used to connect to the Hyperliquid Exchange API. */
transport: HttpTransport | WebSocketTransport;
/** The wallet used to sign requests (viem, ethers or private key directly). */
wallet: AbstractWallet | Hex;
/**
* The network that will be used to sign transactions.
* Must match the network of the {@link wallet}.
*
* Defaults to get chain id from wallet otherwise `0x1`.
*/
signatureChainId?: Hex | (() => MaybePromise<Hex>);
/**
* Sets a default vaultAddress to be used if no vaultAddress is explicitly passed to a method.
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#subaccounts-and-vaults
*/
defaultVaultAddress?: Hex; // Vault address used by default if not provided in method call
/**
* Sets a default expiresAfter to be used if no expiresAfter is explicitly passed to a method.
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#expires-after
*/
defaultExpiresAfter?: number | (() => MaybePromise<number>);
/**
* A fixed nonce or a function that returns a nonce to be used for signing requests.
*
* Defaults to a global nonce manager that uses the current timestamp in milliseconds,
* and increments if the timestamp is not greater than the last nonce.
*
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/nonces-and-api-wallets#hyperliquid-nonces
*/
nonceManager?: number | ((address: string) => MaybePromise<number>);
});
batchModify(params: BatchModifyParameters): Promise<BatchModifySuccessResponse>;
cancel(params: CancelParameters): Promise<CancelSuccessResponse>;
cancelByCloid(params: CancelByCloidParameters): Promise<CancelByCloidSuccessResponse>;
modify(params: ModifyParameters): Promise<ModifySuccessResponse>;
order(params: OrderParameters): Promise<OrderSuccessResponse>;
scheduleCancel(params?: ScheduleCancelParameters): Promise<ScheduleCancelSuccessResponse>;
twapCancel(params: TwapCancelParameters): Promise<TwapCancelSuccessResponse>;
twapOrder(params: TwapOrderParameters): Promise<TwapOrderSuccessResponse>;
updateIsolatedMargin(params: UpdateIsolatedMarginParameters): Promise<UpdateIsolatedMarginSuccessResponse>;
updateLeverage(params: UpdateLeverageParameters): Promise<UpdateLeverageSuccessResponse>;
agentEnableDexAbstraction(): Promise<AgentEnableDexAbstractionSuccessResponse>;
approveAgent(params: ApproveAgentParameters): Promise<ApproveAgentSuccessResponse>;
approveBuilderFee(params: ApproveBuilderFeeParameters): Promise<ApproveBuilderFeeSuccessResponse>;
evmUserModify(params: EvmUserModifyParameters): Promise<EvmUserModifySuccessResponse>;
noop(): Promise<NoopSuccessResponse>;
reserveRequestWeight(params: ReserveRequestWeightParameters): Promise<ReserveRequestWeightSuccessResponse>;
setDisplayName(params: SetDisplayNameParameters): Promise<SetDisplayNameSuccessResponse>;
spotUser(params: SpotUserParameters): Promise<SpotUserSuccessResponse>;
userDexAbstraction(params: UserDexAbstractionExchangeParameters): Promise<UserDexAbstractionSuccessResponse>;
sendAsset(params: SendAssetParameters): Promise<SendAssetSuccessResponse>;
spotSend(params: SpotSendParameters): Promise<SpotSendSuccessResponse>;
usdClassTransfer(params: UsdClassTransferParameters): Promise<UsdClassTransferSuccessResponse>;
usdSend(params: UsdSendParameters): Promise<UsdSendSuccessResponse>;
withdraw3(params: Withdraw3Parameters): Promise<Withdraw3SuccessResponse>;
createSubAccount(params: CreateSubAccountParameters): Promise<CreateSubAccountSuccessResponse>;
subAccountModify(params: SubAccountModifyParameters): Promise<SubAccountModifySuccessResponse>;
subAccountSpotTransfer(params: SubAccountSpotTransferParameters): Promise<SubAccountSpotTransferSuccessResponse>;
subAccountTransfer(params: SubAccountTransferParameters): Promise<SubAccountTransferSuccessResponse>;
claimRewards(): Promise<ClaimRewardsSuccessResponse>;
registerReferrer(params: RegisterReferrerParameters): Promise<RegisterReferrerSuccessResponse>;
setReferrer(params: SetReferrerParameters): Promise<SetReferrerSuccessResponse>;
cDeposit(params: CDepositParameters): Promise<CDepositSuccessResponse>;
cWithdraw(params: CWithdrawParameters): Promise<CWithdrawSuccessResponse>;
linkStakingUser(params: LinkStakingUserParameters): Promise<LinkStakingUserSuccessResponse>;
tokenDelegate(params: TokenDelegateParameters): Promise<TokenDelegateSuccessResponse>;
createVault(params: CreateVaultParameters): Promise<CreateVaultSuccessResponse>;
vaultDistribute(params: VaultDistributeParameters): Promise<VaultDistributeSuccessResponse>;
vaultModify(params: VaultModifyParameters): Promise<VaultModifySuccessResponse>;
vaultTransfer(params: VaultTransferParameters): Promise<VaultTransferSuccessResponse>;
convertToMultiSigUser(params: ConvertToMultiSigUserParameters): Promise<ConvertToMultiSigUserSuccessResponse>;
multiSig(params: MultiSigParameters): Promise<MultiSigSuccessResponse>;
perpDeploy(params: PerpDeployParameters): Promise<PerpDeploySuccessResponse>;
spotDeploy(params: SpotDeployParameters): Promise<SpotDeploySuccessResponse>;
cSignerAction(params: CSignerActionParameters): Promise<CSignerActionSuccessResponse>;
cValidatorAction(params: CValidatorActionParameters): Promise<CValidatorActionSuccessResponse>;
validatorL1Stream(params: ValidatorL1StreamParameters): Promise<ValidatorL1StreamSuccessResponse>;
}
SubscriptionClient
class SubscriptionClient {
constructor(args: {
/** The transport used to connect to the Hyperliquid API. */
transport: WebSocketTransport;
});
activeAssetCtx(params: WsActiveAssetCtxParameters, listener: (data: WsActiveAssetCtxEvent) => void);
activeSpotAssetCtx(params: WsActiveSpotAssetCtxParameters, listener: (data: WsActiveSpotAssetCtxEvent) => void);
allMids(params?: WsAllMidsParameters, listener: (data: WsAllMidsEvent) => void);
assetCtxs(params?: WsAssetCtxsParameters, listener: (data: WsAssetCtxsEvent) => void);
bbo(params: WsBboParameters, listener: (data: WsBboEvent) => void);
candle(params: WsCandleParameters, listener: (data: WsCandleEvent) => void);
l2Book(params: WsL2BookParameters, listener: (data: WsL2BookEvent) => void);
spotAssetCtxs(listener: (data: WsSpotAssetCtxsEvent) => void);
trades(params: WsTradesParameters, listener: (data: WsTradesEvent) => void);
activeAssetData(params: WsActiveAssetDataParameters, listener: (data: WsActiveAssetDataEvent) => void);
clearinghouseState(params: WsClearinghouseStateParameters, listener: (data: WsClearinghouseStateEvent) => void);
notification(params: WsNotificationParameters, listener: (data: WsNotificationEvent) => void);
spotState(params: WsSpotStateParameters, listener: (data: WsSpotStateEvent) => void);
userEvents(params: WsUserEventsParameters, listener: (data: WsUserEventsEvent) => void);
userFundings(params: WsUserFundingsParameters, listener: (data: WsUserFundingsEvent) => void);
userHistoricalOrders(params: WsUserHistoricalOrdersParameters, listener: (data: WsUserHistoricalOrdersEvent) => void);
userNonFundingLedgerUpdates(
params: WsUserNonFundingLedgerUpdatesParameters,
listener: (data: WsUserNonFundingLedgerUpdatesEvent) => void,
);
webData2(params: WsWebData2Parameters, listener: (data: WsWebData2Event) => void);
webData3(params: WsWebData3Parameters, listener: (data: WsWebData3Event) => void);
openOrders(params: WsOpenOrdersParameters, listener: (data: WsOpenOrdersEvent) => void);
orderUpdates(params: WsOrderUpdatesParameters, listener: (data: WsOrderUpdatesEvent) => void);
userFills(params: WsUserFillsParameters, listener: (data: WsUserFillsEvent) => void);
userTwapHistory(params: WsUserTwapHistoryParameters, listener: (data: WsUserTwapHistoryEvent) => void);
userTwapSliceFills(params: WsUserTwapSliceFillsParameters, listener: (data: WsUserTwapSliceFillsEvent) => void);
explorerBlock(listener: (data: WsExplorerBlockEvent) => void);
explorerTxs(listener: (data: WsExplorerTxsEvent) => void);
}
MultiSignClient
class MultiSignClient extends ExchangeClient {
constructor(
args: {
// ... same params as in `ExchangeClient` except `wallet`
// and
multiSigUser: Hex;
signers: [
AbstractWallet | Hex, // leader (first signer), signs the transaction twice
...(AbstractWallet | Hex)[], // ... more signers
];
},
);
}
Transports
Transport is a layer between class/function requests and Hyperliquid servers.
HTTP Transport
Uses fetch for requests. Supports
Info /
Exchange / Explorer endpoints.
Features:
- Can change any settings in the created instance without creating a new instance (e.g. switch between mainnet/testnet).
- Intercepting and modifying requests/responses/errors using on* functions.
class HttpTransport {
constructor(options?: {
/** Whether to use testnet url (default: false) */
isTestnet?: boolean;
/** Request timeout in ms (default: 10_000) */
timeout?: number;
/** Custom server URLs */
server?: {
mainnet?: { api?: string | URL; rpc?: string | URL };
testnet?: { api?: string | URL; rpc?: string | URL };
};
/** Custom fetch options */
fetchOptions?: RequestInit;
/** Callback before request is sent */
onRequest?: (request: Request) => MaybePromise<Request | void | null | undefined>;
/** Callback after response is received */
onResponse?: (response: Response) => MaybePromise<Response | void | null | undefined>;
/** Callback on error during fetching */
onError?: (error: unknown) => MaybePromise<Error | void | null | undefined>;
});
}
WebSocket Transport
Uses WebSocket for requests. Supports
subscriptions and
post requests.
Features:
- Automatically restores connection after loss and resubscribes to previous subscriptions.
- Smart keep alive (pings only when idle).
- Lazy initialization with message buffering during connection establishment.
Limitations:
- 1 instance = 1 immutable endpoint. Cannot mix api/explorer endpoints or mainnet/testnet in single connection. Need to
create separate instances for different endpoints.
- Cannot send explorer post-requests, only explorer subscriptions.
class WebSocketTransport {
constructor(options?: {
/** Indicates this transport uses testnet endpoint (default: false) */
isTestnet?: boolean;
/**
* Custom WebSocket endpoint for API and Subscription requests.
* (default: `wss://api.hyperliquid.xyz/ws` for `isTestnet` = false, `wss://api.hyperliquid-testnet.xyz/ws` for `isTestnet` = true)
*/
url?: string | URL;
/** Timeout for requests in ms (default: 10_000) */
timeout?: number;
/** Interval between sending ping messages in ms (default: 30_000) */
keepAliveInterval?: number;
/** Reconnection policy configuration for closed connections */
reconnect?: {
/** Custom WebSocket constructor (default: global WebSocket) */
WebSocket?: new (url: string | URL) => WebSocket;
/** Maximum number of reconnection attempts (default: 3) */
maxRetries?: number;
/** Maximum time in ms to wait for a connection to open (default: 10_000) */
connectionTimeout?: number;
/** Delay before reconnection in ms (default: Exponential backoff (max 10s)) */
reconnectionDelay?: number | ((attempt: number) => number);
};
/** Enable automatic re-subscription to Hyperliquid subscription after reconnection (default: true) */
resubscribe?: boolean;
});
ready(signal?: AbortSignal): Promise<void>;
close(signal?: AbortSignal): Promise<void>;
}
Errors
All SDK errors extend from HyperliquidError base class for unified error handling:
import { AbstractWalletError, ApiRequestError, HyperliquidError, SchemaError, TransportError } from "@nktkas/hyperliquid";
try {
await exchClient.order({ ... });
} catch (error) {
if (error instanceof SchemaError) {
} else if (error instanceof ApiRequestError) {
} else if (error instanceof TransportError) {
} else if (error instanceof AbstractWalletError) {
} else if (error instanceof HyperliquidError) {
}
}
Additional Import Points
/signing
This module contains functions for generating Hyperliquid transaction signatures.
L1 Action
import { signL1Action } from "@nktkas/hyperliquid/signing";
import { CancelRequest, parser } from "@nktkas/hyperliquid/api/exchange";
import { privateKeyToAccount } from "viem/accounts";
const wallet = privateKeyToAccount("0x...");
const action = parser(CancelRequest.entries.action)({
type: "cancel",
cancels: [
{ a: 0, o: 12345 },
],
});
const nonce = Date.now();
const signature = await signL1Action({ wallet, action, nonce });
const response = await fetch("https://api.hyperliquid.xyz/exchange", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action, signature, nonce }),
});
const body = await response.json();
User Signed Action
import { signUserSignedAction } from "@nktkas/hyperliquid/signing";
import { ApproveAgentRequest, ApproveAgentTypes, parser } from "@nktkas/hyperliquid/api/exchange";
import { privateKeyToAccount } from "viem/accounts";
const wallet = privateKeyToAccount("0x...");
const action = parser(ApproveAgentRequest.entries.action)({
type: "approveAgent",
signatureChainId: "0x66eee",
hyperliquidChain: "Mainnet",
agentAddress: "0x...",
agentName: "Agent",
nonce: Date.now(),
});
const signature = await signUserSignedAction({ wallet, action, types: ApproveAgentTypes });
const response = await fetch("https://api.hyperliquid.xyz/exchange", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action, signature, nonce: action.nonce }),
});
const body = await response.json();
/api
This module contains raw functions for interacting with the Hyperliquid API and
valibot schemas for API requests/responses.
Tree-shaking API functions
You can use raw functions to maximize tree-shaking in your app. This is useful if you are pedantic about bundle size and
want to only include the API calls you use.
/api/info
import { HttpTransport } from "@nktkas/hyperliquid";
import { clearinghouseState } from "@nktkas/hyperliquid/api/info";
const transport = new HttpTransport();
const data = await clearinghouseState(
{ transport },
{ user: "0x..." },
);
/api/exchange
import { HttpTransport } from "@nktkas/hyperliquid";
import { privateKeyToAccount } from "viem/accounts";
import { order } from "@nktkas/hyperliquid/api/exchange";
const wallet = privateKeyToAccount("0x...");
const transport = new HttpTransport();
const data = await order(
{ transport, wallet },
{
orders: [
{
a: 0,
b: true,
p: "30000",
s: "0.1",
r: false,
t: { limit: { tif: "Gtc" } },
c: "0x...",
},
],
grouping: "na",
},
);
/api/subscription
import { WebSocketTransport } from "@nktkas/hyperliquid";
import { candle } from "@nktkas/hyperliquid/api/subscription";
const transport = new WebSocketTransport();
const sub = await candle(
{ transport },
{ coin: "ETH", interval: "1h" },
(data) => console.log(data),
);
Valibot Schemas
Another way to use this module is to access valibot schemas for API
requests/responses. For example, to validate data and sort object keys before creating a signature.
import { OrderRequest, parser } from "@nktkas/hyperliquid/api/exchange";
const action = {
type: "order",
orders: [{
a: 0,
b: true,
p: "50000",
s: "0.1",
r: false,
t: { limit: { tif: "Gtc" } },
}],
grouping: "na",
} satisfies OrderRequest["action"];
const validatedAction = parser(OrderRequest.entries.action)(action);
Also valibot schema can be converted to JSON Schema (e.g. for generating OpenAPI spec):
import { OrderRequest } from "@nktkas/hyperliquid/api/exchange";
import { toJsonSchema } from "@valibot/to-json-schema";
const schema = toJsonSchema(OrderRequest, { errorMode: "ignore", typeMode: "output" });
console.log(JSON.stringify(schema, null, 2));
/utils
This module contains helper functions for interacting with the HyperLiquid API.
SymbolConverter
Helper class for converting asset symbols to asset IDs and size decimals. See
hyperliquid docs.
import { HttpTransport } from "@nktkas/hyperliquid";
import { SymbolConverter } from "@nktkas/hyperliquid/utils";
const transport = new HttpTransport();
const converter = await SymbolConverter.create({ transport });
const converter = await SymbolConverter.create({ transport, dexs: ["test"] });
Get asset ID for a coin
const btcId = converter.getAssetId("BTC");
const hypeUsdcId = converter.getAssetId("HYPE/USDC");
const dexAbcId = converter.getAssetId("test:ABC");
Get size decimals for a coin.
const btcSzDecimals = converter.getSzDecimals("BTC");
const hypeUsdcSzDecimals = converter.getSzDecimals("HYPE/USDC");
const dexAbcSzDecimals = converter.getSzDecimals("test:ABC");
Get spot pair ID for info endpoints and subscriptions
const spotPairId = converter.getSpotPairId("HFUN/USDC");
Formatting functions
Helper functions for formatting price and size based on szDecimals. See
hyperliquid docs.
import { formatPrice, formatSize } from "@nktkas/hyperliquid/utils";
const price = formatPrice("0.0000123456789", 0, false);
const size = formatSize("1.23456789", 5);
Recovering signer address
Recover Address from L1 Action
import { recoverUserFromL1Action } from "@nktkas/hyperliquid/utils";
const action = {
type: "cancel",
cancels: [{ a: 0, o: 12345 }],
};
const nonce = 1700000000000;
const signature = {
r: "0x...",
s: "0x...",
v: 27,
} as const;
const address = await recoverUserFromL1Action({ action, nonce, signature });
console.log(`Signer address: ${address}`);
Recover Address from User Signed Action
import { recoverUserFromUserSigned } from "@nktkas/hyperliquid/utils";
const action = {
type: "approveAgent",
signatureChainId: "0x66eee" as const,
hyperliquidChain: "Mainnet",
agentAddress: "0x...",
agentName: "Agent",
nonce: 1700000000000,
};
const types = {
HyperliquidTransaction: [
{ name: "hyperliquidChain", type: "string" },
],
};
const signature = {
r: "0x...",
s: "0x...",
v: 27,
} as const;
const address = await recoverUserFromUserSigned({ action, types, signature });
console.log(`Signer address: ${address}`);
FAQ
How to execute an L1 action via an external wallet (e.g. MetaMask)?
Hyperliquid requires chain 1337 for L1 action signatures. To handle this with external wallets:
- (recommended) Create an
Agent Wallet
and execute all L1 actions through it
- Change a user's chain to
1337, however, the user will sign unreadable data
How to create a market order?
Hyperliquid doesn't have traditional market orders, but you can achieve market-like execution by placing limit order
with tif: "Ioc" and price that guarantee immediate execution:
- For buys: set limit price >= current best ask
- For sells: set limit price <= current best bid
Use agent's private key instead of master account's private key.
Pass vault or sub-account address via vaultAddress options to method or set defaultVaultAddress in client options.
How to use Testnet?
Set isTestnet: true in transport options.
Contributing
We appreciate your help! To contribute, please read the contributing instructions.