Recently, the FMZ platform has added support for Hyperliquid DEX, a high-performance decentralized exchange, providing users with more options for participating in decentralized tradings. At present, the docker function of the FMZ platform has been fully updated to support Hyperliquid’s spot and perpetual contract tradings, and cover all API functions of the DEX.
Hyperliquid platform overview
Hyperliquid is a high-performance L1 blockchain optimized from scratch, with the vision of building a fully on-chain open financial system. Users can create applications independently by interacting with efficient native components while ensuring a smooth end-user experience.
Hyperliquid L1’s performance is sufficient to support a permissionless financial application ecosystem. All orders, withdrawals, transactions, and liquidations are completed on-chain in a completely transparent manner, with a block latency of less than 1 second. At present, the chain supports a processing capacity of up to 100,000 orders per second.
Hyperliquid L1 uses a custom consensus algorithm called HyperBFT, which is inspired by Hotstuff and its subsequent algorithms. Both the consensus mechanism and the network architecture are optimized from the bottom up to meet the needs of high-performance blockchains.
Through this guide, we hope to help you get started with programmatic and quantitative trading quickly on Hyperliquid DEX on the FMZ platform and discover more trading opportunities.
REST Protocol
Websocket Protocol
On the Add platform page of the FMZ platform, you can configure Hyperliquid spot and futures exchange objects:
Mainnet APP address:
In actual use, the main network is relatively stable and has a good speed.
The corresponding REST protocol API interface node address is: https://api.hyperliquid.xyz
.
The message signature related information is also different: source == "a",chainId = 42161
.
Test network APP address:
The test network often crashes, but it is only used as a test interface and to familiarize yourself with the trading functions on DEX.
The corresponding REST protocol API interface node address is: https://api.hyperliquid-testnet.xyz
.
The message signature related information is also different: source == "b",chainId = 421614
.
Just like the wallet connection method of most DEX exchanges, you can use the wallet APP to scan the QR code to connect to Hyperliquid (switch the wallet to Arbitrum and scan the code to log in, the test network and main network are the same).
You can claim test assets. After receiving the USDC for testing, click the “Deposit” button to deposit it into Hyperliquid (it is best to have some ETH for the Arbitrum test network).
Click the “Deposit” button to deposit, which requires wallet verification and will consume a little ETH on Arbitrum.
When performing manual transactions on the Hyperliquid APP page, the page will automatically generate a proxy wallet address and private key, which are recorded in the browser and used for operations such as placing orders on the browser page. So if we want to do programmatic and quantitative trading, how do we get this configuration information?
You can create the required proxy wallet address and corresponding private key on the Hyperliquid API page:
Then you can configure this information on the FMZ platform (the configuration interface is mentioned above).
Wallet Address: The wallet address connected to Hyperliquid (note, not the proxy wallet address). Wallet PrivateKey: The wallet private key connected to Hyperliquid (optional, only required when calling APIs such as transfers, it can be left blank). Secret Key: Proxy wallet private key (generated in the previous step, the private key displayed after authorization).
Information required to configure the exchange object:
Once the configuration is complete, we can test it on the FMZ platform. We directly use the “debugging tool” of the FMZ platform for testing practice.
If you are using a Hyperliquid exchange object configured with testnet information, you will need to do some switching operations when using it, for example:
function main() {
// REST protocol API address switched to testnet
exchange.SetBase("https://api.hyperliquid-testnet.xyz")
// source : a Mainnet, b Testnet
exchange.IO("source", "b")
return exchange.GetAccount()
}
The mainnet configuration does not require the above switching operation. The API interfaces related to spot and futures products in the Hyperliquid DEX exchange are almost the same, with only slight differences in details. Next, we use the Hyperliquid Futures Exchange objects of the mainnet configuration information and the testnet configuration information for testing.
function main() {
var markets = exchange.GetMarkets()
if (!markets) {
throw "get markets error"
}
var tbl = {
type: "table",
title: "test markets",
cols: [
"key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty",
"MaxQty", "MinNotional", "MaxNotional", "CtVal", "CtValCcy"
],
rows: []
}
for (var symbol in markets) {
var market = markets[symbol]
tbl.rows.push([
symbol, market.Symbol, market.BaseAsset, market.QuoteAsset, market.TickSize, market.AmountSize,
market.PricePrecision, market.AmountPrecision, market.MinQty, market.MaxQty, market.MinNotional, market.MaxNotional, market.CtVal, market.CtValCcy
])
}
LogStatus("`" + JSON.stringify(tbl) + "`")
}
function main() {
var depth = exchange.GetDepth("ETH_USD.swap")
var asks = depth.Asks
var bids = depth.Bids
Log("asks 3", bids[2])
Log("asks 2", bids[1])
Log("asks 1", bids[0])
Log("bids 1", asks[0])
Log("bids 2", asks[1])
Log("bids 3", asks[2])
}
function main() {
var account = exchange.GetAccount()
return account
}
Function results:
function main() {
var symbols = ["ETH_USD.swap", "XRP_USD.swap", "HYPE_USD.swap"]
var arrDir = ["market_buy", "sell", "buy"]
var markets = exchange.GetMarkets()
var ids = []
for (var i in symbols) {
var symbol = symbols[i]
var side = arrDir[i]
var ticker = exchange.GetTicker(symbol)
var info = markets[symbol]
exchange.SetPrecision(info.PricePrecision, info.AmountPrecision)
// USDC
var qty = 15
var price = null
var amount = null
if (side == "market_buy") {
price = -1
side = "buy"
amount = qty / ticker.Last
} else {
price = side == "buy" ? ticker.Last * 0.9 : ticker.Last * 1.1
amount = qty / price
}
var id = exchange.CreateOrder(symbol, side, price, amount)
ids.push(id)
}
var tbl = {type: "table", title: "test", cols: ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"], rows: []}
for (var id of ids) {
var order = exchange.GetOrder(id)
tbl.rows.push([order.Symbol, order.Id, order.Price, order.Amount, order.DealAmount, order.AvgPrice, order.Status, order.Type, order.Offset, order.ContractType])
Sleep(500)
}
LogStatus("`" + JSON.stringify(tbl) + "`")
}
function main() {
var orders = exchange.GetOrders("USD.swap")
for (var order of orders) {
exchange.CancelOrder(order.Id, order)
Sleep(1000)
}
var tbl = {type: "table", title: "test", cols: ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"], rows: []}
for (var order of orders) {
tbl.rows.push([order.Symbol, order.Id, order.Price, order.Amount, order.DealAmount, order.AvgPrice, order.Status, order.Type, order.Offset, order.ContractType])
}
LogStatus("`" + JSON.stringify(tbl) + "`")
}
function main() {
// Set the current position to cross position
exchange.IO("cross", true)
// Set leverage
exchange.SetMarginLevel("ETH_USD.swap", 10)
return exchange.GetRawJSON()
}
Function results:
exchange.GetRawJSON() returns the response information of the leverage setting request:
{“status”:“ok”,“response”:{“type”:“default”}}
Since the interface parameters of the exchange are relatively complex and cannot be passed using the URL encoding method, when using exchange.IOfunction
calls, only JSON strings can be passed in as parameters. The following are examples of various interface calls.
hyperliquid reference documentation: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
var params = {"type": "scheduleCancel", "time": new Date().getTime()}
return exchange.IO("api", "POST", "/exchange", null, JSON.stringify(params))
{“status”:“err”,“response”:“Cannot set scheduled cancel time until enough volume traded. Required: \(1000000. Traded: \)174.57424.”}
This function has restrictions: the account must reach the trading level to use this function.
Create a TWAP order.
function main() {
var params = {
"type": "twapOrder",
"twap": {
"a": 0,
"b": true,
"s": "1",
"r": false,
"m": 10,
"t": false
}
}
// SOL_USDT.swap , Order Quantity: 1 , twapOrder order has position requirement, minimum value of 100 USD
// a: 0, i.e. SOL_USDT.swap
return exchange.IO("api", "POST", "/exchange", null, JSON.stringify(params))
}
Cancel TWAP order.
function main() {
var params = {
"type": "twapCancel",
"a": 0,
"t": 3805
}
return exchange.IO("api", "POST", "/exchange", null, JSON.stringify(params))
}
Testnet, authorize a new proxy wallet.
function main() {
var params = {
"type": "approveAgent",
"hyperliquidChain": "Testnet",
"signatureChainId": "0x66eee",
"agentAddress": "0xAAAA",
"agentName": "test02",
"nonce": new Date().getTime()
}
return exchange.IO("api", "POST", "/exchange", null, JSON.stringify(params))
}
Authorization successfully, returns:
{“status”:“ok”,“response”:{“type”:“default”}}
https://app.hyperliquid-testnet.xyz/API
.Withdraw assets from the vault.
function main() {
var params = {
"type": "vaultTransfer",
"vaultAddress": "0xAAA",
"isDeposit": true,
"usd": 5000000
}
return exchange.IO("api", "POST", "/exchange", null, JSON.stringify(params))
}
Testnet, withdraw assets to wallet.
function main() {
var params = {
"type": "withdraw3",
"hyperliquidChain": "Testnet",
"signatureChainId": "0x66eee",
"amount": "5",
"time": new Date().getTime(),
"destination": "0xAAA"
}
return exchange.IO("api", "POST", "/exchange", null, JSON.stringify(params))
}
Transfer of assets between spot/futures (perpetual contracts).
function main() {
var params = {
"type": "usdClassTransfer",
"hyperliquidChain": "Testnet",
"signatureChainId": "0x66eee",
"amount": "5",
"toPerp": false,
"nonce": new Date().getTime()
}
return exchange.IO("api", "POST", "/exchange", null, JSON.stringify(params))
}
false
, indicating the direction of rotation: futures -> spot.true
, indicating the direction of rotation: spot -> futures.Main network WS interface address:
Mainnet: wss://api.hyperliquid.xyz/ws
Since the REST protocol API interface does not have an interface for obtaining recent transaction data, the Websocket interface has this channel that can be subscribed.
Subscription message structure
{
"method": "subscribe",
"subscription": {
"type": "trades",
"coin": "SOL"
}
}
Example of test executed in debugging tools:
function main() {
var loopCount = 20
var subMsg = {
"method": "subscribe",
"subscription": {
"type": "trades",
"coin": "SOL"
}
}
var conn = Dial("wss://api.hyperliquid.xyz/ws")
conn.write(JSON.stringify(subMsg))
if (conn) {
for (var i = 0; i < loopCount; i++) {
var msg = conn.read(1000)
if (msg) {
Log(msg)
}
}
}
conn.close()
Log("End of test")
}
The above tests are based on the latest docker. You need to download the latest docker to support the Hyperliquid DEX exchange.
Thank you for your support and thank you for reading.