Type/to search
Built-in Functions
Structures
Built-in Variables and Constants
Conventions
Exchanges
Capability Matrix
Centralized Exchanges
Decentralized Exchanges (DEX)
Hyperliquid
Lighter
edgeX
Aster
Aevo
Pendle
WOOFi Pro
Uniswap / PancakeSwap
Aerodrome / Velodrome
KyberSwap
1inch
EVM DEX Common Commands
Jupiter
OKX DEX
DEX Strategy Examples
Prediction Markets
Securities and Futures
On-chain & Custom

Hyperliquid (Spot): The spot market of the Hyperliquid on-chain order book. Market data and account queries need only the wallet address; placing, canceling and amending orders are signed (EIP-712) with the API wallet (agent wallet) private key and need no on-chain gas. Perpetuals and HIP-3 / HIP-4 (Outcome) instruments are served by the Futures_Hyperliquid exchange object.

Futures_Hyperliquid (Futures): USDC-margined perpetuals on the Hyperliquid on-chain order book: perpetuals of the main dex, HIP-3 perpetuals (on builder-deployed dexes, codes carry a dex: prefix) and HIP-4 Outcome (prediction) instruments. Market data and account queries need only the wallet address; orders, cancels, amendments and leverage changes are signed (EIP-712) with the API wallet (agent wallet) private key and need no on-chain gas. Spot is served by the Hyperliquid exchange object.

See the Hyperliquid guide.

Names and Configuration
exchange.GetName()TypeAliases
HyperliquidSpot—
Futures_HyperliquidFuturesHIP-3, HIP-4

✓ marks the exchange objects that have the field.

FieldHyperliquidFutures_HyperliquidRequiredDefaultDescription
Wallet Address✓✓Yes—The main account wallet address (starting with 0x), used as the user of every query other than market data.
Wallet Private Key✓✓No—The main account private key, optional. Used only to sign transfer actions (usdSend, withdraw3 and so on sent with exchange.IO("api", "POST", "/exchange", ...)); not needed for trading.
API Wallet Private Key✓Yes—The private key of an API wallet (agent wallet) created on the Hyperliquid "API" page, used to sign orders, cancels and amendments. Without it only market data and account queries work.
Simulate (testnet)✓✓NoUncheckedUse the Hyperliquid testnet when checked; the API address becomes https://api.hyperliquid-testnet.xyz and trading and transfer actions are signed for the testnet (source is b). A configured node address is still used; the signing network follows the checkbox.
API Wallet Private Key✓Yes—The private key of an API wallet (agent wallet) created on the Hyperliquid "API" page, used to sign orders, cancels, amendments and leverage changes. Without it only market data and account queries work.

Trading Pairs and Contract Codes
Hyperliquid (Spot)

Pair examples: HYPE_USDC, PURR_USDC

Pairs are written as COIN_QUOTE, using Hyperliquid spot token names (for example HYPE, PURR; bridged assets use the exchange's token name, such as UBTC), case-insensitive. The exchange's internal pair names such as @1 and @2 are resolved by the connector from the spot metadata and need not be used directly.

Futures_Hyperliquid (Futures)

Pair examples: BTC_USD, xyz:XYZ100_USD, BTC-above-100k---Dec_USD

Perpetual pairs are written as COIN_USD (COIN_USDC is accepted too; returned symbols always use USD), with USDC as margin, for example BTC_USD.swap. The connector restores the coin's case from the exchange's instrument list (such as kPEPE). HIP-3 pairs carry a dex prefix, kept lowercase, for example xyz:XYZ100_USD.swap.

A HIP-4 Outcome pair is the market name (spaces and / replaced by -) plus _USD, and the contract code is the name of the outcome side, for example BTC-above-100k---Dec_USD.Yes; when several markets share a name, -<market id> is appended to tell them apart (such as Recurring-1399_USD.Yes), and the bare name fails as ambiguous. exchange.GetMarkets() lists the available Outcome codes.

Contract codeDescription
swapPerpetual contract; the main dex and HIP-3 instruments are perpetual only.

There are no delivery contracts. The contract code of an Outcome instrument is the outcome side name (such as Yes, No), not swap.

Exchange-specific IO Commands
Hyperliquid (Spot)
CommandArgumentsDescriptionReturns
walletAddressaddressSet the address used by read-only queries (assets, orders, order history), so another address's assets can be queried; the wallet that signs orders is unchanged. To query your own account again, pass the configured wallet address.The address set.
vaultAddressaddressPlace, cancel and amend orders on behalf of a vault or sub-account (the address goes into the signature and the request body); an empty string clears it. Queries still use the wallet address; to query the vault's assets and orders, also set walletAddress to the vault address.The address set.
expiresAftertimestampSet the expiresAfter carried by all subsequent signed actions (orders, cancels, amendments, ...), a Unix timestamp in milliseconds after which the exchange rejects the action; 0 clears it (the default). The value stays in effect, so every action after that time is rejected until it is set again or reset to 0.The value set.
source"a" | "b"The network used for signing: a is mainnet (the default; b when the Simulate (testnet) box is checked), b is testnet. (more below the table)The value set.
apimethod, path[, params[, body]]Call a Hyperliquid endpoint directly. (more below the table)The raw exchange response.

The rest of the longer descriptions in the table:

  • source: It sets the source field of the Agent signature of trading actions and the chainId of the EIP-712 signature of transfer actions (usdSend, spotSend, withdraw3, ...): Arbitrum 42161 on mainnet, Arbitrum Sepolia 421614 on testnet. The API address is not changed; to connect to the testnet also switch it with exchange.IO("base", "https://api.hyperliquid-testnet.xyz").
  • api: A POST to /exchange takes an action object, and the connector adds the nonce and signs it; transfer actions (usdSend, spotSend, withdraw3, usdClassTransfer, approveAgent, approveBuilderFee, userSetAbstraction) are signed with the wallet private key WalletPrivateKey, and fields such as hyperliquidChain must be filled in by the caller; other actions are signed with the API wallet private key. Other paths (such as POST /info) are sent as they are, unsigned. body (a JSON object or a JSON string), when given, is the request body (the action for /exchange); otherwise params is used as the body; a body of any other type is an error.

For the common commands base and currency see exchange.IO.

Futures_Hyperliquid (Futures)
CommandArgumentsDescriptionReturns
crossboolCross (true, the default) / isolated (false) margin. Only recorded by the connector, not per contract, and submitted together with the leverage on the next exchange.SetMarginLevel() call for any contract; the command itself sends no request.cross or isolated.
dexnameSet the default HIP-3 dex name (without :, such as xyz; list the names with exchange.IO("api", "POST", "/info", {type: "perpDexs"})). (more below the table)The dex name set (an empty string when cleared).
walletAddressaddressSet the address used by read-only queries (account, positions, orders), so another address's positions can be queried; the wallet that signs orders is unchanged. To query your own account again, pass the configured wallet address.The address set.
vaultAddressaddressPlace, cancel and amend orders and set leverage on behalf of a vault or sub-account (the address goes into the signature and the request body); an empty string clears it. Queries still use the wallet address; to query the vault's account and positions, also set walletAddress to the vault address.The address set.
expiresAftertimestampSet the expiresAfter carried by all subsequent signed actions (orders, cancels, amendments, leverage changes, ...), a Unix timestamp in milliseconds after which the exchange rejects the action; 0 clears it (the default). The value stays in effect, so every action after that time is rejected until it is set again or reset to 0.The value set.
source"a" | "b"The network used for signing: a is mainnet (the default; b when the Simulate (testnet) box is checked), b is testnet. (more below the table)The value set.
splitsymbol, amountHIP-4 Outcome split (the splitOutcome action) of amount for the Outcome that symbol belongs to, into positions on each outcome side. (more below the table)The raw exchange response (status is ok).
mergesymbol[, amount]HIP-4 Outcome merge (the mergeOutcome action) of the positions on each side of the Outcome that symbol belongs to; amount is optional, and when omitted or not above 0 the request carries no amount.The raw exchange response (status is ok).
mergeQuestionsymbol[, amount]HIP-4 merge by question (the mergeQuestion action) for the question that the Outcome of symbol belongs to; amount is optional (when omitted or not above 0 the request carries no amount). Fails if the Outcome belongs to no question.The raw exchange response (status is ok).
negatesymbol, amountHIP-4 negation (the negateOutcome action) of the Outcome of symbol within its question; amount must be greater than 0. Fails if the Outcome belongs to no question.The raw exchange response (status is ok).
apimethod, path[, params[, body]]Call a Hyperliquid endpoint directly. (more below the table)The raw exchange response.

The rest of the longer descriptions in the table:

  • dex: Once set, range queries without a symbol (GetPositions(), GetOrders(), GetConditionOrders(), GetTickers(), GetMarkets()) cover only this dex, while GetTickers() and GetMarkets() still add all HIP-4 Outcome instruments. An empty string clears it and restores the default, where these queries gather the main dex and all HIP-3 dexes. Calls with a symbol always follow the symbol's own dex prefix. The name is not checked when set; an unknown name fails on the next range query.
  • source: It sets the source field of the Agent signature of trading actions and the chainId of the EIP-712 signature of transfer actions (usdSend, withdraw3, usdClassTransfer, ...): Arbitrum 42161 on mainnet, Arbitrum Sepolia 421614 on testnet. The API address is not changed; to connect to the testnet also switch it with exchange.IO("base", "https://api.hyperliquid-testnet.xyz"). The testnet has no HIP-3, so range queries cover the main dex only.
  • split: symbol is an Outcome code (such as BTC-above-100k---Dec_USD.Yes), written as for market data and orders (markets sharing a name take the code with -<market id> (such as Recurring-1399_USD.Yes) and the bare name fails as ambiguous); the symbol of merge, mergeQuestion and negate follows the same rule. amount must be greater than 0.
  • api: A POST to /exchange takes an action object, and the connector adds the nonce and signs it; transfer actions (usdSend, spotSend, withdraw3, usdClassTransfer, approveAgent, approveBuilderFee, userSetAbstraction) are signed with the wallet private key WalletPrivateKey, and fields such as hyperliquidChain must be filled in by the caller; other actions are signed with the API wallet private key. Other paths (such as POST /info) are sent as they are, unsigned. body (a JSON object or a JSON string), when given, is the request body (the action for /exchange); otherwise params is used as the body; a body of any other type is an error.

For the common commands base and currency see exchange.IO.

Common Usage
Query the Info endpoint with api and read another address's account
javascript
function main() { // POST /info is unsigned; the params object is the request body var mids = exchange.IO("api", "POST", "/info", {type: "allMids"}) Log("BTC mid:", mids["BTC"], "HYPE mid:", mids["HYPE"]) var meta = exchange.IO("api", "POST", "/info", {type: "spotMeta"}) Log("Spot tokens:", meta.tokens.length, "spot pairs:", meta.universe.length) // Later account and order queries target this address (the HLP vault here); the wallet // that signs orders is unchanged. Pass the configured wallet address to query your own // account again exchange.IO("walletAddress", "0xdfc24b077bc1425ad1dea75bcb6f8158e10df303") Log("Account of that address:", exchange.GetAccount()) Log("Open orders of that address:", exchange.GetOrders()) }
Trade on behalf of a vault or sub-account
javascript
function main() { var vault = "0x..." // replace with the vault or sub-account address // Later orders, cancels and amendments are signed and sent on behalf of the vault exchange.IO("vaultAddress", vault) // Queries still use the wallet address; set it as well to query the vault exchange.IO("walletAddress", vault) Log("Vault account:", exchange.GetAccount()) var orders = exchange.GetOrders() for (var i = 0; i < orders.length; i++) { exchange.CancelOrder(orders[i].Id) } // An empty string clears it; later actions are the wallet's own again exchange.IO("vaultAddress", "") }
Give signed actions an expiry time
javascript
function main() { // Later signed actions (orders, cancels, amendments, ...) expire in 10 seconds; the // exchange rejects actions that arrive after that time exchange.IO("expiresAfter", Date.now() + 10 * 1000) var orders = exchange.GetOrders() for (var i = 0; i < orders.length; i++) { if (!exchange.CancelOrder(orders[i].Id)) { Log("Cancel failed:", GetLastError()) } } // The value stays in effect; reset it to 0, or every later action is rejected exchange.IO("expiresAfter", 0) }
Send a transfer action with api, moving USDC between the spot and perpetual accounts
javascript
function main() { // Transfer actions are signed with the "Wallet Private Key" option; the caller fills in // hyperliquidChain, signatureChainId and the other fields var r = exchange.IO("api", "POST", "/exchange", { type: "usdClassTransfer", hyperliquidChain: "Mainnet", // Testnet on the testnet signatureChainId: "0xa4b1", // signing chain ID 42161; 0x66eee (421614) on testnet amount: "10", // a string toPerp: true, // true: spot to perp; false: perp to spot nonce: Date.now() }) Log(r) }
List the HIP-3 dexes and query the instruments and positions of one of them (Futures_Hyperliquid only)
javascript
function main() { // perpDexs: the first item is the main dex (null), followed by the HIP-3 dexes var dexs = exchange.IO("api", "POST", "/info", {type: "perpDexs"}) var names = [] for (var i = 0; i < dexs.length; i++) { if (dexs[i]) { names.push(dexs[i].name) } } Log("HIP-3 dexes:", names.join(", ")) // Later range queries without a symbol cover only xyz (GetMarkets and GetTickers // always add the HIP-4 Outcome instruments) exchange.IO("dex", "xyz") var markets = exchange.GetMarkets() var n = 0 for (var k in markets) { if (k.indexOf("xyz:") == 0) { n++ } } Log("Perpetuals on xyz:", n) Log("Positions on xyz:", exchange.GetPositions()) // Calls with a symbol follow the symbol's own dex prefix, whatever IO("dex") says Log(exchange.GetTicker("xyz:XYZ100_USD.swap")) // An empty string clears it; range queries gather the main dex and all HIP-3 dexes again exchange.IO("dex", "") }
Find HIP-4 Outcome instruments and the questions they belong to (Futures_Hyperliquid only)
javascript
function main() { // Rows of GetMarkets() with Info.isOutcome true are Outcome instruments, and // Info.outcomeId is the Outcome number var markets = exchange.GetMarkets() var byId = {} for (var k in markets) { var info = markets[k].Info if (info.isOutcome) { byId[info.outcomeId] = byId[info.outcomeId] || [] byId[info.outcomeId].push(k) } } // A question consists of several Outcomes (namedOutcomes) plus a fallback Outcome var meta = exchange.IO("api", "POST", "/info", {type: "outcomeMeta"}) Log("Outcomes:", meta.outcomes.length, "questions:", meta.questions.length) var q = meta.questions[0] Log("Question", q.question, q.description) for (var i = 0; i < q.namedOutcomes.length; i++) { Log("Outcome", q.namedOutcomes[i], byId[q.namedOutcomes[i]]) } Log("Fallback Outcome", q.fallbackOutcome, byId[q.fallbackOutcome]) var symbol = byId[q.namedOutcomes[0]][0] Log(symbol, exchange.GetDepth(symbol)) }
Split, merge and negate HIP-4 Outcome positions (Futures_Hyperliquid only)
javascript
function main() { var symbol = "BTC-above-100k---Dec_USD.Yes" // replace with an Outcome code of GetMarkets() // Split: an amount of 10 into positions on each side of the Outcome; must be above 0 var r = exchange.IO("split", symbol, 10) Log("split:", r ? r.status : GetLastError()) // Merge the positions on each side back; the amount may be omitted r = exchange.IO("merge", symbol, 10) Log("merge:", r ? r.status : GetLastError()) // negate and mergeQuestion only work for an Outcome that belongs to a question r = exchange.IO("negate", symbol, 10) Log("negate:", r ? r.status : GetLastError()) r = exchange.IO("mergeQuestion", symbol) Log("mergeQuestion:", r ? r.status : GetLastError()) }

Function Support
Hyperliquid (Spot)

Not supported (the call fails with an error and returns null): exchange.CreateConditionOrder, exchange.ModifyConditionOrder, exchange.CancelConditionOrder, exchange.GetConditionOrder, exchange.GetConditionOrders, exchange.GetHistoryConditionOrders.

Served through a fallback:

  • exchange.GetRecords: Native periods are 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 8h, 12h, 1d, 3d, 1w, 1M; other periods are synthesized by the docker.
Futures_Hyperliquid (Futures)

No unsupported standard functions.

Served through a fallback:

  • exchange.GetRecords: Native periods are 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 8h, 12h, 1d, 3d, 1w; other periods are synthesized by the docker. Outcome instruments have no bars.

Margin, Account and Simulation
Futures_Hyperliquid (Futures)

Margin mode: Choose cross/isolated margin with exchange.IO("cross", bool); it is submitted together with the leverage on the next exchange.SetMarginLevel() (the exchange's updateLeverage action). The leverage is truncated to an integer. HIP-3 margin is kept per dex.

Position mode: One-way positions only. Closing orders (closebuy, closesell) are sent as reduce-only.

Account: For a unified account or portfolio margin account, the balance and equity of exchange.GetAccount() come from the spot USDC balance and the unrealized PnL from the perpetual account; a standard account reads the perpetual account (for HIP-3, the dex of the current symbol). The balance currency is USDC.

Notes
Hyperliquid (Spot)
  • Market orders are sent as IOC orders priced at the mid price ±0.5%; the amount of a market buy is the number of coins to buy, not a quote-currency amount. An explicit {type: "limit"} with a price of 0 or below is an error; it is never sent as a market order.
  • Order options go in the last object argument: {tif: "ioc"} for IOC and {postOnly: true} for post-only (the exchange's Alo, not allowed on market orders); fok is not supported on limit orders and fails. builder (builder fee, {b: builder address, f: integer fee}) and grouping are merged into the order action and signed with it; other keys are ignored.
  • Prices allow at most 5 significant figures and at most 8 minus the coin's size decimals (szDecimals) decimal places; integer prices are always valid. TickSize and PricePrecision of exchange.GetMarkets() are computed at the magnitude of the current price, so the tick changes when the price crosses a power of 10: for example HYPE_USDC (szDecimals 2) has a tick of 0.001 below 100 and 0.01 from 100 up. An order or amendment whose price breaks the rule fails with an error that gives the tick at that price and the nearest valid prices on both sides; the price is not rounded automatically. The protective price of a market order is rounded by the connector according to the rule.
  • AvgPrice of an order is the actual average fill price aggregated per order from the exchange's fill records (userFillsByTime), and 0 when nothing is filled. For a few seconds after a fill the exchange's fill records may not be updated yet; AvgPrice is then 0 (or the average of the fills already recorded) and is accurate when queried again shortly afterwards. The exchange keeps only the latest 10000 fills, so orders filled earlier report 0. Fill records are queried only for filled orders, and the results are cached.
  • After a successful exchange.ModifyOrder() the order ID changes; the return value is the new order ID.
  • Buy and Sell of exchange.GetTicker() are the best bid and ask (the mid price when one side is empty); Last, High and Low are all the mid price, as the exchange has no 24h high/low. Buy and Sell of exchange.GetTickers() are the mid price too.
  • exchange.GetHistoryOrders() returns only the recent orders the exchange provides; the since parameter is not supported and a since greater than 0 fails.
Futures_Hyperliquid (Futures)
  • Market orders are sent as IOC orders priced at the mid price ±0.5%; for Outcome instruments ±1% (bounded to 0.001–0.999). A conditional order that executes at market after triggering is priced at the mid price ±0.5% as well. An explicit {type: "limit"} with a price of 0 or below is an error; it is never sent as a market order.
  • Order options go in the last object argument: {tif: "ioc"} for IOC and {postOnly: true} for post-only (the exchange's Alo; an error on conditional orders and on market orders of Outcome instruments; other market orders are always IOC); fok is not supported on limit orders and fails. builder (builder fee, {b: builder address, f: integer fee}) and grouping are merged into the order action and signed with it; orders (a non-empty array) replaces the order legs built by the connector entirely, with the legs written by the caller in the exchange's format; other keys are ignored.
  • Prices allow at most 5 significant figures and at most 6 minus the contract's size decimals (szDecimals) decimal places; integer prices are always valid. TickSize and PricePrecision of exchange.GetMarkets() are computed at the magnitude of the current price, so the tick changes when the price crosses a power of 10. An order or amendment (including the order price of a conditional order) whose price breaks the rule fails with an error that gives the tick at that price and the nearest valid prices on both sides; the price is not rounded automatically. The protective price of a market order is rounded by the connector according to the rule. HIP-4 Outcome instruments are not checked locally.
  • AvgPrice of orders and conditional orders is the actual average fill price aggregated per order from the exchange's fill records (userFillsByTime), and 0 when nothing is filled. For a few seconds after a fill the exchange's fill records may not be updated yet; AvgPrice is then 0 (or the average of the fills already recorded) and is accurate when queried again shortly afterwards. The exchange keeps only the latest 10000 fills, so orders filled earlier report 0. Fill records are queried only for filled orders, and the results are cached.
  • Conditional orders support take-profit and stop-loss, not OCO; take-profit and stop-loss are separate trigger orders. After a successful exchange.ModifyOrder() or exchange.ModifyConditionOrder() the order ID changes; the return value is the new order ID.
  • Last of exchange.GetTicker() and exchange.GetTickers() is the mid price; Buy and Sell are the exchange's bid/ask impact prices (not the best bid and ask; use exchange.GetDepth() for those), and High/Low take the same impact prices, as the exchange has no 24h high/low.
  • exchange.GetFundings(): the main dex returns predicted funding rates (settled hourly); HIP-3 instruments need an explicit symbol and return the funding records of the last 24 hours.
  • exchange.GetHistoryOrders() and exchange.GetHistoryConditionOrders() return only the recent orders the exchange provides; the since parameter is not supported and a since greater than 0 fails.
  • HIP-4 Outcome instruments are spot-like holdings: trade them by buying and selling (integer amounts); reduce-only is not supported, so closing orders (closebuy, closesell) fail; holdings come from the Outcome tokens in the spot account. Outcome instruments have no bars or funding rates, and Last of GetTicker() is the mid price while Buy and Sell are 0. An Outcome instrument the exchange has no mid price for yet (newly listed, not traded yet, and so on) is still listed by GetMarkets() (PricePrecision is 4 and Info.assetCtx.midPx is null), is left out of GetTickers(), and fails GetTicker() and market orders; a holding of it is valued at a mid price of 0 (Margin is 0 and Profit is minus the entry cost).