Trang này được dịch tự động. Bản gốc tiếng Anh là phiên bản chính thức. Đọc bằng tiếng Anh →
Chuyển đến nội dung chính

Ký EIP-712

Trang này là tài liệu tham chiếu ở cấp trường dữ liệu cho mọi thông điệp EIP-712 mà Hypercall xác minh: ba domain ký directive (ví API, Manager, RSM), các thông điệp perp chỉ xử lý off-chain dùng chung domain ví API, và domain độc lập Physical Covered Call Quote. Lệnh quyền chọn trên REST API dùng một domain khác là Hypercall; xem Xác thực & Ký.

Mọi nội dung ở đây đã được đối chiếu với các hợp đồng triển khai trên mạng chính HyperEVM (chain ID 999): Exchange 0.6.1 tại 0xE6b7FaA216cabb2b38B392f577C9c826378b2240 và Account 0.2.4. Các domain separator và typehash bên dưới đều được nhúng trong bytecode đã triển khai đó.

Tổng quan​

Một directive là một hành động trên một Account, được ký off-chain và được sequencer của Hypercall gửi lên on-chain thông qua Exchange.executeUserDirective hoặc Exchange.executeRsmDirective. Account khôi phục người ký từ digest EIP-712 và kiểm tra quyền:

  1. Ví API: một địa chỉ được đăng ký trên Account bằng hc_update_api_wallet (Account.isApiWalletActive). Ký lệnh đặt và lệnh hủy.
  2. Manager: chủ sở hữu Account (Account.manager). Ký các thay đổi ví API, chuyển tài sản và thay đổi chế độ tài khoản.
  3. Người ký RSM: do giao thức kiểm soát (Exchange.rsmSigner). Ký các khoản ghi có, rút tiền, directive thanh lý và lệnh phục hồi chỉ giảm vị thế. Người dùng không bao giờ ký các thông điệp này.

Mã hóa Directive​

Trên on-chain, một directive là abi.encodePacked(account, nonce, version, id, data):

ByteTrườngÝ nghĩa
20accountĐịa chỉ Account (address)
8nonceNonce của người ký (uint64)
1versionNhóm hành động
3idID hành động trong nhóm
phần còn lạidataabi.encode của struct hành động bên trong
VersionNhómID hành động
0HyperCall (HC)2 cập nhật ví API. 1 (chuyển quyền chọn) được dành riêng và bị từ chối.
1HyperLiquid (HL)1 lệnh giới hạn, 9 thêm ví API, 10 hủy theo oid, 11 hủy theo cloid, 13 gửi tài sản, 16 đặt abstraction
255System1 ghi có token, 2 ghi có quyền chọn, 3 bắt đầu thanh lý, 4 dừng thanh lý, 5 rút token

Bạn không cần tự xây dựng chuỗi byte này. Hãy ký dữ liệu có kiểu, sau đó gửi account, nonce, action và signature tới API, API sẽ mã hóa directive.

Cấu trúc dữ liệu có kiểu​

Mọi directive đều có cùng cấu trúc bên ngoài: địa chỉ Account, nonce của người ký và một struct hành động bên trong.

<Outer>(address account,uint64 nonce,<Inner> action)<Inner>(...)

Chuỗi kiểu bên ngoài được nối thêm định nghĩa kiểu bên trong, nên typehash bao phủ cả hai. Theo thuật ngữ EIP-712, primaryType là tên bên ngoài, types chứa cả hai mục, và message là { account, nonce, action }. Thứ tự trường là một phần của chuỗi kiểu và phải khớp chính xác.

Các entrypoint nạp tiền không cần chữ ký​

Không phải lệnh gọi nạp tiền nào cũng là hành động EIP-712. Các phương thức sau là giao dịch trực tiếp do ví thanh toán hoặc router gửi:

function depositUsdcFor(address account, uint256 amount) external;
function depositOption(address account, address token, uint256 amount) external;

depositUsdcFor được thiết kế không cần chữ ký vì msg.sender chỉ là bên thanh toán USDC. Tài khoản Hypercall được ghi có là đối số account tường minh và trường sự kiện UsdcDeposit.account. Router và zap có thể gọi phương thức này, vì vậy indexer và dịch vụ backend không được dùng msg.sender để xác định tài khoản được ghi có.

depositOption đốt token quyền chọn từ msg.sender và phát sự kiện Deposit(account, msg.sender, token, amount) cho indexer RSM. Luồng ghi có quyền chọn hoạt động theo sự kiện và không dùng chữ ký manager, agent hay RSM từ người nạp.

Domain độc lập: Báo giá Physical Covered Call​

Báo giá covered call giao vật chất được xác minh bởi factory triển khai trên chuỗi đã chọn. Chúng không dùng bộ xác minh của Exchange hay domain địa chỉ zero của nó.

Domain:

{
"name": "Hypercall Physical Covered Call",
"version": "1",
"chainId": "<selected chain id>",
"verifyingContract": "<exact PhysicalCoveredCallFactory address>"
}

Người ký: nhà tạo lập thị trường được mã hóa trong PhysicalCoveredCallQuote.marketMaker.

Các kiểu lồng nhau chuẩn:

AssetTerms(address underlyingWrapper)

OptionTerms(address seller,uint256 underlyingAmount,uint64 strikeX8,uint64 expiry)

PhysicalCoveredCallRequest(bytes32 rfqId,AssetTerms asset,OptionTerms option)AssetTerms(address underlyingWrapper)OptionTerms(address seller,uint256 underlyingAmount,uint64 strikeX8,uint64 expiry)

PhysicalCoveredCallQuote(bytes32 requestHash,bytes32 quoteId,address marketMaker,uint256 premiumSettlement,uint64 quoteDeadline,uint64 nonce)

Factory tính lại requestHash từ toàn bộ yêu cầu lồng nhau trước khi khôi phục người ký báo giá. Do đó chữ ký ràng buộc người bán, wrapper tài sản cơ sở, số lượng share của wrapper, giá thực hiện, ngày đáo hạn, phí quyền chọn, hạn chót báo giá, nonce, chain id và địa chỉ factory. Token thanh toán và số thập phân là cấu hình có thẩm quyền của factory, không phải giá trị được ký riêng. Thế hệ không dùng oracle này không có Pyth. Cả digest báo giá lẫn nonce của nhà tạo lập đều bị tiêu thụ khi người bán nạp tiền vào vault.

Chỉ người bán được mã hóa trong yêu cầu mới có thể gửi báo giá đã ký. Việc nạp tiền sẽ mint NFT quyền yêu cầu của người bán quyền chọn cho người bán và NFT quyền chọn vị thế mua cho nhà tạo lập thị trường đã báo giá, với điều kiện nhà tạo lập đó là bên nhận hợp lệ khi danh sách cho phép người mua (tùy chọn) đang bật. Một chữ ký hợp lệ cho phép nạp tiền, không cho phép thực hiện quyền chọn.

Chỉ chủ sở hữu hiện tại của NFT quyền chọn vị thế mua mới được gọi thực hiện quyền. Quy tắc chỉ-chủ-sở-hữu này ngăn một operator ERC-721 tiêu dùng allowance token thanh toán của chủ sở hữu. Operator được phê duyệt vẫn có thể chuyển NFT theo quy tắc ERC-721 tiêu chuẩn, qua đó chuyển quyền lợi kinh tế cho một bên nhận hợp lệ khi cổng người mua đang bật. Việc thực hiện quyền thành công sẽ kéo tiền theo giá thực hiện từ người gọi (chủ sở hữu), giao tài sản cơ sở cho chủ sở hữu đó và đốt NFT quyền chọn vị thế mua.

Domain Separator EIP-712​

Ba domain directive dùng cùng cấu trúc và chỉ khác nhau ở name. verifyingContract là địa chỉ zero, nên cùng một chữ ký hợp lệ với mọi Account trên chuỗi, và chính địa chỉ Account bên trong thông điệp mới ràng buộc chữ ký với một Account cụ thể.

{
"name": "<DomainName>",
"version": "1",
"chainId": <chainId>,
"verifyingContract": "0x0000000000000000000000000000000000000000"
}

Kiểu domain là EIP712Domain(string name,string version,uint256 chainId,address verifyingContract).

Chain ID: mạng chính 999, testnet 998. Account chọn separator theo chuỗi mà nó đang chạy, vì vậy chữ ký trên testnet không bao giờ được xác minh trên mạng chính.

DomainnameversionNgười kýChuỗiSeparator
Ví APIHypercallApiSign1Ví API9990x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb
Ví APIHypercallApiSign1Ví API9980x339bee4c00da9a5361f687797205c8d03f323659f5d9dc9e0505b9437ddee25e
ManagerHypercallManagerSign1Manager9990xc9b5b0b8b0d9d7ba716326acbf795cfe431ef960a25a8f958d6569bea2f1516e
ManagerHypercallManagerSign1Manager9980xd1f76b6138be892c14b71b0569bdb049cb44f239d34c78ef1ffaacd2466f9f18
RSMHypercallRsmSign1Người ký RSM9990x3d0cae2af623c614099dbadd67a1e1457fabde576aa270a70a57e39bf338a7be
RSMHypercallRsmSign1Người ký RSM9980x650b282053fb61d3fd477bdc28f6434311fe905e27cc4ca643e87e802c45938c

Hãy tự tính separator và so sánh trước khi ký bất cứ thứ gì:

import { ethers } from "ethers";

const separator = ethers.TypedDataEncoder.hashDomain({
name: "HypercallApiSign",
version: "1",
chainId: 999,
verifyingContract: ethers.ZeroAddress
});
// 0x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb

Tham chiếu thông điệp​

Ma trận người ký và endpoint​

Thông điệpDomainNgười kýGửi tớiThực thi
HLOrderAPIVí APIPOST /v1/tee-perp/orders/submit, hoặc POST /v1/actions/hl_limit_orderLệnh giới hạn Hyperliquid
HLCancelAPIVí APIPOST /v1/tee-perp/cancels/submit-by-oid, hoặc POST /v1/actions/hl_cancel_by_oidHủy theo oid
HLCancelByCloidAPIVí APIPOST /v1/tee-perp/cancels/submit, hoặc POST /v1/actions/hl_cancel_by_cloidHủy theo cloid
HCPerpTriggerOrderAPIVí APIPOST /v1/tee-perp/orders/submit-triggerLệnh kích hoạt gốc (chỉ TEE)
HCPerpOrderBatchAPIVí APIPOST /v1/tee-perp/orders/submit-batchLô lệnh gốc (chỉ TEE)
HCPerpLeverageChangeAPIVí APIPOST /v1/tee-perp/leverage/submitCập nhật đòn bẩy (chỉ TEE)
HCPerpScheduleCancelAPIVí APIPOST /v1/tee-perp/schedule-cancel/submitCông tắc dead-man (chỉ TEE)
HCUpdateApiWalletManagerManagerPOST /v1/actions/hc_update_api_walletSổ đăng ký ví API của Account
HLAddApiWalletManagerManagerPOST /v1/actions/hl_add_api_walletPhê duyệt ví API trên HyperCore
HLSendAssetManagerManagerPOST /v1/actions/hl_send_assetsendAsset trên HyperCore từ Account
HLSetAbstractionManagerManagerPOST /v1/actions/hl_set_abstractionChế độ tài khoản HyperCore (chỉ unified)
HCTransferOptionManagerManagerKhông được chấp nhậnDành riêng, bị từ chối on-chain
HLOrder, HLCancel, HLCancelByCloid, HLSendAssetRSMNgười ký RSMChỉ sequencerLệnh phục hồi và sweep thông qua Account
System*RSMNgười ký RSMChỉ sequencerGhi có, rút tiền, thanh lý thông qua Exchange

Mọi route /v1/actions/{action} đều nhận account, nonce, action và signature. POST /v1/actions/{action}/typed-data trả về chính xác dữ liệu có kiểu cần ký cho yêu cầu đó, đây là cách dễ nhất để xác nhận bộ mã hóa của bạn. GET /v1/directives/{directive_id} báo cáo kết quả on-chain. Schema yêu cầu nằm trong Tham chiếu API.

Quy ước dữ liệu truyền​

  • nonce và mọi trường uint64, uint128 hoặc uint256 là số nguyên JSON tối đa 9007199254740991, hoặc chuỗi thập phân. Dùng chuỗi cho giá trị lớn hơn mức đó.
  • signature là chuỗi hex 0x dài 65 byte (r || s || v). v có thể là 0, 1, 27 hoặc 28.
  • Các trường bytes32 là hex 32 byte có tiền tố 0x. Địa chỉ ở dạng hex có checksum hoặc chữ thường.
  • Giá và khối lượng perp là số nguyên 1e8 của HyperCore, ví dụ $50,000 là 5000000000000 và 0.001 coin là 100000.

Directive ví API (HypercallApiSign)​

Được ký bởi một ví API đang hoạt động của Account. Dùng chain ID 999, name là HypercallApiSign.

Các test vector dùng một account giữ chỗ và một nonce cố định để bạn có thể kiểm tra bộ mã hóa của mình đến từng byte. Digest là keccak256(0x1901 || domainSeparator || directiveStructHash).

HLOrder​

Một lệnh giới hạn Hyperliquid cho Account.

Struct:

struct LimitOrder {
uint32 asset;
bool isBuy;
uint64 limitPx;
uint64 sz;
bool reduceOnly;
uint8 encodedTif;
uint128 cloid;
}

struct HLOrder {
address account;
uint64 nonce;
LimitOrder action;
}

Kiểu EIP-712 chuẩn:

HLOrder(address account,uint64 nonce,LimitOrder action)LimitOrder(uint32 asset,bool isBuy,uint64 limitPx,uint64 sz,bool reduceOnly,uint8 encodedTif,uint128 cloid)

Typehash: 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd. Người ký: ví API. Hành động: version 1, id 1.

  • asset: chỉ số tài sản Hyperliquid. GET /v1/tee-perp/markets liệt kê các thị trường perp mà Hypercall chấp nhận cùng chỉ số của chúng.
  • isBuy: true để mua, false để bán.
  • limitPx, sz: giá và khối lượng nhân 1e8.
  • reduceOnly: true nếu lệnh chỉ được phép giảm vị thế.
  • encodedTif: ALO = 1, GTC = 2, IOC = 3. Mọi giá trị khác đều bị từ chối.
  • cloid: ID lệnh của client, khác không. Bạn dùng nó sau này để hủy theo cloid.

Ví dụ (ethers.js):

const domain = {
name: "HypercallApiSign",
version: "1",
chainId: 999,
verifyingContract: ethers.ZeroAddress
};

const types = {
LimitOrder: [
{ name: "asset", type: "uint32" },
{ name: "isBuy", type: "bool" },
{ name: "limitPx", type: "uint64" },
{ name: "sz", type: "uint64" },
{ name: "reduceOnly", type: "bool" },
{ name: "encodedTif", type: "uint8" },
{ name: "cloid", type: "uint128" }
],
HLOrder: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "LimitOrder" }
]
};

const message = {
account: managedAccount,
nonce: selectedNonce,
action: {
asset: 0,
isBuy: true,
limitPx: 5000000000000n,
sz: 100000n,
reduceOnly: false,
encodedTif: 2,
cloid: selectedNonce
}
};

const signature = await apiWalletSigner.signTypedData(domain, types, message);

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd
Hash struct hành động0x0fd024c6bf8f132123e63a78d50008d8c39c52e5409ef6ca87a4eec8f6eabb41
Hash struct directive0xd32948ee1f249b96124a6acdb5845d09aad8228512098598de6858d5484fe703
Digest cần ký0xc3c42699092fe20c7dbc4205a1027f55c28d33a682a64bd3f04e40f1d28693f5

Test vector dùng isBuy: true, limitPx: 5000000000000, sz: 100000, reduceOnly: false, encodedTif: 2, asset: 0, và cloid bằng nonce.

Gửi: POST /v1/tee-perp/orders/submit với account, nonce, action và signature. Hypercall chạy kiểm tra ký quỹ, sau đó một enclave bảo mật ký và gửi lệnh Hyperliquid gốc kèm builder code của Hypercall. Manager của Account trước tiên phải phê duyệt builder đó bằng Account.approveZeroFeeBuilder; xem Bắt đầu sử dụng. Xem Perps để biết toàn bộ luồng xử lý.

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 1760000000000,
"action": {
"asset": 0,
"isBuy": true,
"limitPx": "5000000000000",
"sz": "100000",
"reduceOnly": false,
"encodedTif": 2,
"cloid": "1760000000000"
},
"signature": "0x<65 byte signature>"
}

Cùng thông điệp đã ký đó cũng được chấp nhận tại POST /v1/actions/hl_limit_order, route này mã hóa nó thành một directive on-chain được thực thi qua Exchange.executeUserDirective và Account.performCoreAction.

HLCancel​

Hủy một lệnh theo ID lệnh Hyperliquid. Wrapper là HLCancel và struct bên trong là CancelOrderByOid.

struct CancelOrderByOid {
uint32 asset;
uint64 oid; // Order ID assigned by HyperCore
}

struct HLCancel {
address account;
uint64 nonce;
CancelOrderByOid action;
}
HLCancel(address account,uint64 nonce,CancelOrderByOid action)CancelOrderByOid(uint32 asset,uint64 oid)

Typehash: 0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85. Người ký: ví API. Hành động: version 1, id 10. Gửi: POST /v1/tee-perp/cancels/submit-by-oid, hoặc POST /v1/actions/hl_cancel_by_oid.

const types = {
CancelOrderByOid: [
{ name: "asset", type: "uint32" },
{ name: "oid", type: "uint64" }
],
HLCancel: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "CancelOrderByOid" }
]
};

const message = {
account: managedAccount,
nonce: selectedNonce,
action: { asset: 0, oid: 123456789n }
};

const signature = await apiWalletSigner.signTypedData(domain, types, message);

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85
Hash struct hành động0xa34e7bb8af0d099f9c48095924e53067bcb9b542a816445b96abebbc5646b727
Hash struct directive0x69d560ba5ef3e88459bde7fb8252e55dbc33627373c8f0cfcf8ef0868f59e097
Digest cần ký0x5046aba9fb33c55ce736faf63734ea66914f3f168ff0aff2229fa6f31fa9b330

Test vector dùng asset: 0 và oid: 123456789.

HLCancelByCloid​

Hủy một lệnh theo ID lệnh của client mà bạn đã đặt trong HLOrder.

struct CancelOrderByCloid {
uint32 asset;
uint128 cloid; // Client order ID
}

struct HLCancelByCloid {
address account;
uint64 nonce;
CancelOrderByCloid action;
}
HLCancelByCloid(address account,uint64 nonce,CancelOrderByCloid action)CancelOrderByCloid(uint32 asset,uint128 cloid)

Typehash: 0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5. Người ký: ví API. Hành động: version 1, id 11. Gửi: POST /v1/tee-perp/cancels/submit, hoặc POST /v1/actions/hl_cancel_by_cloid.

const types = {
CancelOrderByCloid: [
{ name: "asset", type: "uint32" },
{ name: "cloid", type: "uint128" }
],
HLCancelByCloid: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "CancelOrderByCloid" }
]
};

const message = {
account: managedAccount,
nonce: selectedNonce,
action: { asset: 0, cloid: 1760000000000n }
};

const signature = await apiWalletSigner.signTypedData(domain, types, message);

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5
Hash struct hành động0xfa4ab6440f946a6e279d90972d71223c768c01c8a91dc22703a6448dbcb966d0
Hash struct directive0x998efb01bb9c842eea80e8cc084b9e4e7ec13b2111790e1acbfec32e49060d9d
Digest cần ký0x56af82a6aa7fa50907a23c6cfe3aa556af5aa087b1157163ebf6ea0240e8d29d

Test vector dùng asset: 0 và cloid: 1760000000000.

Thông điệp perp chỉ dành cho TEE​

Bốn thông điệp này được API Hypercall xác minh, không phải hợp đồng Account, vì enclave thực thi chúng trực tiếp trên Hyperliquid và không tồn tại directive on-chain nào cho chúng. Chúng dùng cùng domain HypercallApiSign và cùng cơ chế phân quyền ví API như HLOrder (người ký phải là ví API đang hoạt động của Account, và Account phải ở chế độ ký quỹ danh mục). Typehash của chúng không có trong các hợp đồng. Nonce là thời gian Unix tính bằng mili giây.

PerpOrderTerms​

HCPerpTriggerOrder và HCPerpOrderBatch đều nhúng struct này. Một lệnh con giới hạn ký byte TIF của nó với triggerPx = 0, isMarket = false, tpsl = 0. Một lệnh con kích hoạt ký encodedTif = 0, một triggerPx dương, và tpsl là 1 (chốt lời) hoặc 2 (cắt lỗ).

struct PerpOrderTerms {
uint32 asset;
bool isBuy;
uint64 limitPx;
uint64 sz;
bool reduceOnly;
uint8 encodedTif;
uint64 triggerPx;
bool isMarket;
uint8 tpsl;
uint128 cloid;
}

HCPerpTriggerOrder​

Một lệnh cắt lỗ hoặc chốt lời, gửi tới POST /v1/tee-perp/orders/submit-trigger. action.orderType của yêu cầu phải là lệnh kích hoạt.

struct HCPerpTriggerOrder {
address account;
uint64 nonce;
PerpOrderTerms order;
}
HCPerpTriggerOrder(address account,uint64 nonce,PerpOrderTerms action)PerpOrderTerms(uint32 asset,bool isBuy,uint64 limitPx,uint64 sz,bool reduceOnly,uint8 encodedTif,uint64 triggerPx,bool isMarket,uint8 tpsl,uint128 cloid)

Typehash: 0x2d3104ab255275839aad254429e4be789f64a8d16b8e3e7d5f30a0db3c887b5c

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x2d3104ab255275839aad254429e4be789f64a8d16b8e3e7d5f30a0db3c887b5c
Hash struct hành động0x285b3186be219b92d7159419288c0dce9bc4ad7bfc9536e009ebf24bd67f434c
Hash struct directive0xaa03e40b34b15e7e932ae827921930e7538387b596ef1040dbcc791e69021299
Digest cần ký0xc46aadc390b66c235af15e199e188ab23fb7f7f1b9237f6c2849c264c28d94da

Test vector là một lệnh bán cắt lỗ dạng thị trường chỉ giảm vị thế: asset: 0, isBuy: false, limitPx: 4800000000000 (giá xấu nhất), sz: 100000, reduceOnly: true, encodedTif: 0, triggerPx: 4900000000000, isMarket: true, tpsl: 2, cloid: 1760000000001.

HCPerpOrderBatch​

Tối đa 100 lệnh trong một nhóm, gửi tới POST /v1/tee-perp/orders/submit-batch. Mỗi lệnh phải dùng một cloid riêng biệt. grouping là 0 (không nhóm), 1 (normalTpsl), hoặc 2 (positionTpsl). Một lô được tính là một lần đặt lệnh đối với giới hạn tốc độ.

struct HCPerpOrderBatch {
address account;
uint64 nonce;
uint8 grouping;
PerpOrderTerms[] orders;
}
HCPerpOrderBatch(address account,uint64 nonce,uint8 grouping,PerpOrderTerms[] orders)PerpOrderTerms(uint32 asset,bool isBuy,uint64 limitPx,uint64 sz,bool reduceOnly,uint8 encodedTif,uint64 triggerPx,bool isMarket,uint8 tpsl,uint128 cloid)

Typehash: 0x9d4f467a44f4b0d39f234f3b91888546ce31dcbb67ce791550901b9042c38f8b. Mảng orders được mã hóa thành keccak256 của các hash struct PerpOrderTerms nối liền nhau, theo thứ tự gửi.

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x9d4f467a44f4b0d39f234f3b91888546ce31dcbb67ce791550901b9042c38f8b
Hash mảng lệnh0x13fc75fcc69bf3b4ef7cdc3a0872c3cc1cf59440c74d366055109b6bd5ea7c98
Hash struct directive0x69d0b1131e386769823fe1ab3facbe8e6fc013f86a117cf95cb52b8ce2f274e0
Digest cần ký0x4b5cd34b1f254fdd9881b7674a3412807e16cade1f2ccc7a1e261482682fbd07

Test vector là grouping: 1 với hai lệnh: một lệnh mua giới hạn GTC (limitPx: 5000000000000, sz: 100000, cloid: 1760000000000) tiếp theo là lệnh cắt lỗ từ ví dụ lệnh kích hoạt.

HCPerpLeverageChange​

Đặt đòn bẩy cho một tài sản, gửi tới POST /v1/tee-perp/leverage/submit. leverage phải lớn hơn không.

struct PerpLeverageChange {
uint32 asset;
bool isCross;
uint32 leverage;
}

struct HCPerpLeverageChange {
address account;
uint64 nonce;
PerpLeverageChange action;
}
HCPerpLeverageChange(address account,uint64 nonce,PerpLeverageChange action)PerpLeverageChange(uint32 asset,bool isCross,uint32 leverage)

Typehash: 0xe13845f0e6c16a5e1fc56b2d11fb0972faa2ec30b01e94d58c72147fa9b6a463

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0xe13845f0e6c16a5e1fc56b2d11fb0972faa2ec30b01e94d58c72147fa9b6a463
Hash struct hành động0x0e6e271dd56192d7fb1f37ea2eaffecfbbe2d1f79cac78dce6a6930bb8cc253e
Hash struct directive0xe04b169bbb0e20042308e5aad1036ce60eda75f484a4d6093dc60f2c2231129e
Digest cần ký0xb2a43487152a7cecc73d2b6b84d817a58dd02c559b05289a8d8e1b5c3d25e266

Test vector đặt đòn bẩy cross 5x cho asset: 0.

HCPerpScheduleCancel​

Công tắc dead-man của Hyperliquid: hủy mọi lệnh đang mở tại thời điểm time (mili giây Unix, ít nhất bảy giây trong tương lai). Gửi tới POST /v1/tee-perp/schedule-cancel/submit. Để xóa lệnh hủy đã lên lịch, hãy bỏ time trong yêu cầu và ký time = 0. Gửi giá trị 0 tường minh sẽ bị từ chối.

struct PerpScheduleCancel {
uint64 time;
}

struct HCPerpScheduleCancel {
address account;
uint64 nonce;
PerpScheduleCancel action;
}
HCPerpScheduleCancel(address account,uint64 nonce,PerpScheduleCancel action)PerpScheduleCancel(uint64 time)

Typehash: 0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb
Hash struct hành động0x0a3ebfe48ef28a79beeee4d56e524f8a5280c38562efb697e7b1d63b3d475afc
Hash struct directive0xae64a13943a6a35b33aeb3095763b855c58c2119daf71e1e3228d8acf2645e8b
Digest cần ký0xa01806f47299010b5963a516562be3c3b44fed4f4a9e2e56c4bb601630146cdc

Test vector lên lịch hủy tại time: 1760000060000.

Lệnh hủy chuẩn bị sẵn do Manager ký​

POST /v1/tee-perp/cancels/submit-prepared là luồng hủy do manager ký. Luồng này không dùng struct dữ liệu có kiểu. Manager ký digest của một lệnh hủy Hyperliquid gốc đã được chuẩn bị sẵn, cung cấp dưới dạng preparedRequest (base64) cùng managerSignature ở dạng low-s chuẩn, kèm theo một authenticationSignature có dấu thời gian để xác thực ví manager. Xem Tham chiếu API để biết schema yêu cầu.

Directive Manager (HypercallManagerSign)​

Được ký bởi manager của Account. Dùng chain ID 999, name là HypercallManagerSign. Account yêu cầu signer == manager. Gửi bằng POST /v1/actions/{action}.

HCUpdateApiWallet​

Thêm, thay thế hoặc xóa (addr = 0x0) ví API được lưu dưới name trên Account.

struct UpdateApiWallet {
bytes32 name; // Wallet label, ASCII left-aligned and zero padded
address addr; // API wallet address, zero to remove
}

struct HCUpdateApiWallet {
address account;
uint64 nonce;
UpdateApiWallet action;
}
HCUpdateApiWallet(address account,uint64 nonce,UpdateApiWallet action)UpdateApiWallet(bytes32 name,address addr)

Typehash: 0x8ebe7d19374200e5dc3ae838db74b370da95bd2b3a8aec9de85d2398dd4a9257. Hành động: version 0, id 2. Gửi: POST /v1/actions/hc_update_api_wallet với action là { "name": "0x...", "addr": "0x..." }.

const domain = {
name: "HypercallManagerSign",
version: "1",
chainId: 999,
verifyingContract: ethers.ZeroAddress
};

const types = {
UpdateApiWallet: [
{ name: "name", type: "bytes32" },
{ name: "addr", type: "address" }
],
HCUpdateApiWallet: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "UpdateApiWallet" }
]
};

const message = {
account: accountAddress,
nonce: selectedNonce,
action: {
name: ethers.encodeBytes32String("trading-bot"),
addr: apiWalletAddress
}
};

const signature = await managerSigner.signTypedData(domain, types, message);

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x8ebe7d19374200e5dc3ae838db74b370da95bd2b3a8aec9de85d2398dd4a9257
Hash struct hành động0x8b6c4a9db102e9d27c9a4069b39ba35e04948129359f0c15cd5103dd101ffce7
Hash struct directive0x830e291835ad182f290bc3d2bff09eaf9fd33acfbe44c6ad583218cd1a8232e5
Digest cần ký0x06589077544af449314db1fa8c7aac2d277cce9e833a04992d88161ede24cbe8

Test vector dùng name là trading-bot (0x74726164696e672d626f74 được đệm số 0 bên phải) và addr là 0x2222222222222222222222222222222222222222. Xem Bắt đầu sử dụng để biết toàn bộ luồng ví API. Account phát sự kiện ApiWalletUpdated(name, addr).

HLAddApiWallet​

Phê duyệt một ví API Hyperliquid cho Account trên HyperCore.

struct AddApiWallet {
address apiWalletAddress;
string apiWalletName; // An empty name replaces the main API wallet
}

struct HLAddApiWallet {
address account;
uint64 nonce;
AddApiWallet action;
}
HLAddApiWallet(address account,uint64 nonce,AddApiWallet action)AddApiWallet(address apiWalletAddress,string apiWalletName)

Typehash: 0x71c0e0dfbddc3456015249946354324befde42b6851d1c9b26c6a29f2e0b1ac2. Hành động: version 1, id 9. Gửi: POST /v1/actions/hl_add_api_wallet.

apiWalletName là một string, nên trường struct của nó là keccak256(bytes(apiWalletName)). Ethers và viem tự động xử lý việc này.

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x71c0e0dfbddc3456015249946354324befde42b6851d1c9b26c6a29f2e0b1ac2
Hash struct hành động0xed32a441b0ee59c0252f5dff3411766289c9c35c19e3152b0b2b204176c2c7cd
Hash struct directive0xb990a3dfb4e8d96243539f8758b3a55249b217542bb4112f4f88ed67ec516ed9
Digest cần ký0x584886d020316085de0e0dec16331b8e990558be3e8fd004c47200abbebed518

Test vector dùng apiWalletAddress là 0x2222222222222222222222222222222222222222 và apiWalletName là hl-bot.

HLSendAsset​

Gửi tài sản từ Account trên HyperCore tới một địa chỉ đích.

struct SendAsset {
address destination; // Recipient
address subAccount; // Recipient sub-account, zero for main
uint32 srcDex; // Source dex: 0 = perps, 4294967295 = spot
uint32 dstDex; // Destination dex: 0 = perps, 4294967295 = spot
uint64 token; // HyperCore token index (0 = USDC)
uint64 amountWei; // Amount in HyperCore wei (USDC: 1e8 per dollar)
}

struct HLSendAsset {
address account;
uint64 nonce;
SendAsset action;
}
HLSendAsset(address account,uint64 nonce,SendAsset action)SendAsset(address destination,address subAccount,uint32 srcDex,uint32 dstDex,uint64 token,uint64 amountWei)

Typehash: 0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595. Hành động: version 1, id 13. Gửi: POST /v1/actions/hl_send_asset.

const types = {
SendAsset: [
{ name: "destination", type: "address" },
{ name: "subAccount", type: "address" },
{ name: "srcDex", type: "uint32" },
{ name: "dstDex", type: "uint32" },
{ name: "token", type: "uint64" },
{ name: "amountWei", type: "uint64" }
],
HLSendAsset: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "SendAsset" }
]
};

const message = {
account: accountAddress,
nonce: selectedNonce,
action: {
destination: recipientAddress,
subAccount: ethers.ZeroAddress,
srcDex: 0,
dstDex: 0xFFFFFFFF, // spot
token: 0, // USDC
amountWei: 500000000n // 5 USDC
}
};

const signature = await managerSigner.signTypedData(domain, types, message);

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595
Hash struct hành động0x9b8c0290da19ea1069e14833023c4621a4f043354b36b4f17d4803b1fce6e656
Hash struct directive0xa0cb8a72188a61289fc2685c29a424605e0a2ee7b7af3e8cfee10e1c75153e08
Digest cần ký0x7c7037f27c659a1885f744778480e6847c5d08e98fb22517265ba708b6597d10

Test vector gửi 5 USDC (amountWei: 500000000) từ perps (srcDex: 0) sang spot (dstDex: 4294967295) với destination là Exchange production 0xE6b7FaA216cabb2b38B392f577C9c826378b2240.

HLSetAbstraction​

Đặt chế độ tài khoản HyperCore của Account. Account chỉ chấp nhận user bằng chính nó và abstraction = 2 (tài khoản unified); mọi giá trị khác đều revert. Ký quỹ danh mục (Portfolio Margin) yêu cầu chế độ này.

struct SetAbstraction {
address user; // Must equal the Account
uint8 abstraction; // Must be 2 (unified account)
}

struct HLSetAbstraction {
address account;
uint64 nonce;
SetAbstraction action;
}
HLSetAbstraction(address account,uint64 nonce,SetAbstraction action)SetAbstraction(address user,uint8 abstraction)

Typehash: 0xcf5fddf081e5f2a9a45aa87cb1a3c42e5aa20164566b1ad2369b6b1318eac786. Hành động: version 1, id 16. Gửi: POST /v1/actions/hl_set_abstraction.

Test vector (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0xcf5fddf081e5f2a9a45aa87cb1a3c42e5aa20164566b1ad2369b6b1318eac786
Hash struct hành động0xef6c70a3c14b9e77c710c6b3b3ee681ca270ef884bd8a64fa4064a96f3dda84e
Hash struct directive0xdda9d0fe82b63c728c4ac42585d5998a04cabaed0f957a2cafdf31a754829c3d
Digest cần ký0xf49d7d8d74596e503d6a1bdfb26653533a12a5ba3816acd992d0bd4ef378f59d

Test vector đặt user là Account và abstraction là 2.

HCTransferOption (dành riêng)​

Các hợp đồng định nghĩa HCTransferOption(address account,uint64 nonce,TransferOption action)TransferOption(address recipient,address option,uint256 amountWei) (typehash 0xa218e1158788b23987f954edc7a07659a03a03fe5ba981a5bbe44d7a146e0819, hành động version 0, id 1), nhưng không có loại người ký nào được gán cho nó. Account revert với Account__UserDirectiveNotSupported, và API từ chối hc_transfer_option. Không ký thông điệp này. Thay vào đó, hãy chuyển token quyền chọn bằng depositOption và lệnh rút.

Giao dịch Manager không cần chữ ký​

Một số hành động của manager là lệnh gọi trực tiếp tới Account, không phải thông điệp EIP-712: Account.approveZeroFeeBuilder(builder) phê duyệt một builder Hyperliquid với phí tối đa 0% và bắt buộc phải gọi một lần trước lệnh perp đầu tiên (xem Bắt đầu sử dụng). Account.transferTo(recipient, token, amount) chuyển token ra khỏi Account trên HyperEVM. Cả hai đều yêu cầu msg.sender == manager và revert khi Account đang trong quá trình thanh lý.

Directive RSM (HypercallRsmSign)​

Được ký bởi người ký RSM và được sequencer gửi đi. Chúng ghi có tiền nạp, xử lý rút tiền, bắt đầu và dừng thanh lý, và đặt lệnh phục hồi IOC chỉ giảm vị thế. Nhà tạo lập thị trường và người dùng không ký hay gửi các thông điệp này; chúng được mô tả ở đây để bạn có thể kiểm chứng những gì giao thức có thể thực hiện trên một Account. Dùng chain ID 999, name là HypercallRsmSign. Exchange kiểm tra signer == rsmSigner (hiện là 0x502E7fAbF34E84EeB115C34FE947b79A94dF886E trên mạng chính) và bên gọi phải có SEQUENCER_ROLE.

Lệnh và sweep RSM (do Account thực thi)​

Các thông điệp này tái sử dụng struct HL dưới domain RSM, nên typehash giống hệt bên API và manager, chỉ có domain separator khác. Account áp dụng thêm các ràng buộc và vẫn thực thi chúng ngay cả khi đang thanh lý.

Thông điệpTypehashRàng buộc do Account áp dụng
HLOrder0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707ddencodedTif phải là IOC (3), và lệnh phải là reduceOnly, hoặc là lệnh bán spot sang USDC (asset id spot từ 10000 đến 99999) với giới hạn không thấp hơn quá 5% so với giá spot trên HyperCore
HLCancel0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85Không có
HLCancelByCloid0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5Không có
HLSendAsset0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595destination phải là Exchange

Test vector HLOrder RSM (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd
Hash struct hành động0x39b4e0699f382aaad23f04740034e7c5581ba918139d2db63fbf586cc447e7db
Hash struct directive0xe6dde5ad6d310b5ebb83c09ec28ee5568700473b885bb483b7437dca202af4f3
Digest cần ký0x57afa1e810804e768c05a467aa88ede15fdceedae5aaa840adff61a613aca469

Vector HLOrder RSM là một lệnh bán IOC chỉ giảm vị thế (isBuy: false, limitPx: 4800000000000, sz: 100000, reduceOnly: true, encodedTif: 3, cloid bằng nonce). Exchange.executeRsmDirective xác minh chữ ký và chuyển hành động tới Account.

Hành động System (do Exchange thực thi)​

Version 255. Mỗi wrapper có dạng System<Action>(address account,uint64 nonce,<Action> action)<Action>(...).

WrapperKiểu bên trongTypehash
SystemCreditTokenCreditToken(uint32 srcDex,uint32 dstDex,uint64 token,uint64 amountWei)0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052
SystemCreditOptionCreditOption(bytes32 underlying,uint256 expiry,uint256 strike,bool isCall,uint256 amountWei)0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae
SystemStartLiquidationStartLiquidation(int256 equity,uint256 marginNeeded)0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e
SystemStopLiquidationStopLiquidation(uint256 startTime)0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3
SystemWithdrawTokenWithdrawToken(address destination,address subAccount,uint32 srcDex,uint32 dstDex,uint64 token,uint64 amountWei)0x634b866e9a922bb846e297973c7a456e641b88f4e97493da9b222084d799c883

Chuỗi kiểu bên ngoài đầy đủ:

SystemCreditToken(address account,uint64 nonce,CreditToken action)CreditToken(uint32 srcDex,uint32 dstDex,uint64 token,uint64 amountWei)
SystemCreditOption(address account,uint64 nonce,CreditOption action)CreditOption(bytes32 underlying,uint256 expiry,uint256 strike,bool isCall,uint256 amountWei)
SystemStartLiquidation(address account,uint64 nonce,StartLiquidation action)StartLiquidation(int256 equity,uint256 marginNeeded)
SystemStopLiquidation(address account,uint64 nonce,StopLiquidation action)StopLiquidation(uint256 startTime)
SystemWithdrawToken(address account,uint64 nonce,WithdrawToken action)WithdrawToken(address destination,address subAccount,uint32 srcDex,uint32 dstDex,uint64 token,uint64 amountWei)
  • SystemCreditToken ghi có token spot hoặc perp từ HyperCore vào Account. amountWei phải khác không và Account phải được kích hoạt trên HyperCore.
  • SystemCreditOption mint token quyền chọn cho Account, triển khai cặp quyền chọn nếu cần. underlying là một word ShortString của OpenZeppelin: ASCII căn trái với độ dài byte ở byte cuối cùng (BTC là 0x42544300...03). Các cách mã hóa không chuẩn sẽ revert.
  • SystemStartLiquidation ghi lại tham số đấu giá và khóa Account. marginNeeded phải khác không.
  • SystemStopLiquidation yêu cầu startTime bằng thời điểm bắt đầu đã ghi nhận và trả Account về cho manager.
  • SystemWithdrawToken xếp hàng việc chuyển USDC tiêu chuẩn trên HyperCore từ số dư của chính Exchange. Nó yêu cầu subAccount = 0, srcDex = 0, dstDex là 0 hoặc 4294967295, token = 0 (USDC), và amountWei là bội số nguyên của đơn vị EVM. Biên lai trên HyperEVM tự nó không chứng minh việc chuyển tiền đã hoàn tất trên HyperCore.

Test vector SystemCreditToken (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052
Hash struct hành động0xc69d7c6e5c36c9789d990c6316eaff3be43980583806f41f8a8e6461b7114011
Hash struct directive0x7ffa37cef7e08d3a2dd5501a8648899d37bc09ebb25d148c124e12c5047476e1
Digest cần ký0x95f75e5ddb4837de3f578b8aa0d714d4b02672b18c4929e3d2dda4a266de8254

Vector ghi có 5 USDC (srcDex và dstDex là 4294967295, token: 0, amountWei: 500000000).

Test vector SystemCreditOption (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae
Hash struct hành động0x4a8b563fc94d26c1da376145d5aa5d05f996232fcf9739ed0a662650e91861b6
Hash struct directive0x190b638f1a462469bf0d070248acfc86bbbb95ea8a9d3d97d33581c7d6bb5554
Digest cần ký0x86fb7c53bb7e139a4d5df7db2feae40e634efe09ea7509165d3cece75d75fce2

Vector ghi có một quyền chọn mua BTC (underlying: 0x42544300...03, expiry: 1761811200, strike: 80000, isCall: true, amountWei: 1000000000000000000).

Test vector SystemStartLiquidation (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e
Hash struct hành động0x4cd6a7f0997eba84ef82eabd429a0d9ca80e55bd6d89d2e67eda9970d87ec803
Hash struct directive0x84f18dc2577978d7890c9eb269fd787d99de37039b3a08e24745398feffbd0c5
Digest cần ký0xcc72c0e7829938c9ca0a4515d759f94cc96d2f24cd51a134a430f215ed5f5d4b

Vector dùng equity: -1500000000 và marginNeeded: 20000000000 (cả hai đều là USDC sáu chữ số thập phân).

Test vector SystemStopLiquidation (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3
Hash struct hành động0x1d900a795b328bd5fa734bd6d7f74634b98ca66eb5e45322fb1ba6400564b62b
Hash struct directive0x977b9becdd26830f2cdf70ab40f72f24490fe6ed45822d1fc8c84120e9a46f40
Digest cần ký0xbe65f82782b14dba42e334e32dd7dcc6bf14c96824523723a186a7381f8f12af

Vector dùng startTime: 1760000000.

Test vector SystemWithdrawToken (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):

BướcGiá trị
Typehash0x634b866e9a922bb846e297973c7a456e641b88f4e97493da9b222084d799c883
Hash struct hành động0x10bd8d4372a09e613a6b4fb7018fcccde857ebf6cc3327d6c9a3c0f81515a076
Hash struct directive0x86680427965513c65a7a170730b9f4fb2e2b40e22cd18338cb004b6a7872ada2
Digest cần ký0x65cc392038decb9ccdc23b0a4a1cfbe657d3417f8cd9ebf2319b3172fb7d885c

Vector rút 5 USDC (amountWei: 500000000) tới destination là 0x1111111111111111111111111111111111111111 với srcDex: 0, dstDex: 0, token: 0.

Nonce​

Mỗi người ký có một không gian nonce độc lập, được theo dõi ở ba nơi.

  • Hợp đồng Account: một bitmap cho mỗi người ký. Account.isNonceUsed(signer, nonce) trả về việc nonce đã được tiêu thụ hay chưa. Một directive người dùng sẽ revert với Account__NonceAlreadyUsed khi dùng lại nonce. Không có nextNonce; được phép có khoảng trống và thứ tự không quan trọng trên on-chain.
  • Hợp đồng Exchange: một bitmap cho người ký RSM, đọc bằng Exchange.isNonceUsed(signer, nonce).
  • Engine: lưu 100 nonce cao nhất cho mỗi người ký. Nonce mới không được nằm trong tập này, phải lớn hơn nonce nhỏ nhất đã lưu khi tập đã đầy, và phải nằm nghiêm ngặt trong khoảng từ hai ngày trước đến một ngày sau thời gian máy chủ tính bằng mili giây.

Dùng thời gian Unix hiện tại tính bằng mili giây làm giá trị khởi đầu của nonce và tăng dần theo từng người ký. Hai yêu cầu do cùng một ví ký trong cùng một mili giây cần nonce khác nhau, vì vậy hãy duy trì một bộ đếm. Với các route perp TEE, nonce còn là mốc thời gian của yêu cầu, nên hãy dùng dấu thời gian mili giây thực tế thay vì số nguyên nhỏ.

function isNonceUsed(address signer, uint256 nonce) external view returns (bool);

Luồng xác minh chữ ký​

  1. Off-chain: người ký xây dựng digest EIP-712 (0x1901 || domainSeparator || structHash) và ký nó.
  2. API: Hypercall khôi phục người ký, kiểm tra đó là ví API đang hoạt động hoặc manager, chạy kiểm tra ký quỹ của engine đối với lệnh, sau đó đưa directive vào hàng đợi. Phản hồi báo cáo đúng giai đoạn xử lý, chi tiết từ chối và hash giao dịch.
  3. Sequencer: gửi Exchange.executeUserDirective(directive, signature). Exchange kiểm tra Account tồn tại và chuyển tiếp tới Account.executeUserDirective.
  4. Account: dựng lại digest từ chính địa chỉ của nó, nonce và hành động, khôi phục người ký bằng separator API hoặc manager tương ứng với hành động đó, kiểm tra quyền, tiêu thụ nonce rồi thực thi. Hành động HL được chuyển tới CoreWriter của HyperCore. Hành động HC cập nhật sổ đăng ký ví API.
  5. Client: thăm dò GET /v1/directives/{directive_id} để lấy trạng thái cuối cùng.

Các route perp TEE dừng sau bước API: enclave, chứ không phải Account, thực thi lệnh trên Hyperliquid.

Example (HLOrder):
1. API wallet signs HLOrder with the managed account, a unique nonce, and one LimitOrder action
2. Client posts account, nonce, action, and signature to /v1/tee-perp/orders/submit
3. Hypercall recovers the API wallet and applies portfolio-margin admission
4. The enclave signs and sends the native Hyperliquid order with the Hypercall builder code
5. Client reads the stage from the response and polls for subsequent status

Không còn được hỗ trợ và đã loại bỏ​

Các thành phần sau từng xuất hiện trong các phiên bản trước của trang này và không còn là một phần của hệ thống đã triển khai. Chúng được liệt kê để các tích hợp xây dựng dựa trên chúng có thể được chuyển đổi.

  • Mã hóa Processor và ActionCaster. Hợp đồng Processor và cách mã hóa thông điệp ActionCaster đã bị loại bỏ trong Exchange 0.2.0 (tháng 2 năm 2026). Directive của Account hiện đi qua Exchange.executeUserDirective và CoreWriter. Exchange 0.6.1 đã triển khai không còn entrypoint cũ nào.
  • Entrypoint Exchange với struct riêng. hlRequestOrder, hlRequestCancel, hlRequestCancelByCloid, hlActionSendAsset, hcActionWithdrawToken, hcActionWithdrawOption, rsmCommandRebalance và rsmCommandRepay đã bị loại bỏ. Các thay thế tương ứng:
Thông điệp đã loại bỏThay thế
HLRequestCancel (lô HLCancel{asset,oid} cộng nonce)HLCancel với một CancelOrderByOid cho mỗi directive
HLRequestCancelByCloidHLCancelByCloid với một CancelOrderByCloid cho mỗi directive
HLActionSendAsset (account, nonce, destination, srcDex, dstDex, token, amountWei)HLSendAsset với SendAsset, bổ sung thêm subAccount
HCActionWithdrawTokenSystemWithdrawToken do RSM ký, được sequencer thực thi sau khi engine phê duyệt lệnh rút
HCActionWithdrawOptionGhi có quyền chọn là SystemCreditOption của RSM; nạp tiền dùng depositOption
RsmCommandRebalanceHLOrder do RSM ký (IOC chỉ giảm vị thế)
RsmCommandRepayHLSendAsset do RSM ký gửi tới Exchange
  • Các hàm lệnh cũ. placeCoreOrders, cancelCoreOrders và cancelCoreOrdersByCloid dùng cách mã hóa MsgPack và domain CoreSignatures ("Exchange", chain ID 1337). Chúng đã bị loại bỏ.
  • nextNonce. Bộ đếm on-chain nextNonce[signer] không còn tồn tại. Chỉ còn bitmap nonce đã dùng (isNonceUsed).
  • Separator mạng chính được đánh dấu TBD. Nội dung trước đây liệt kê separator manager và RSM trên mạng chính là TBD. Cả ba hiện đã được cố định và liệt kê ở trên.
  • HCTransferOption. Đã được định nghĩa nhưng chưa bao giờ được kích hoạt; xem ở trên.

Lưu ý bảo mật​

  1. Khóa: giữ khóa manager trên ví phần cứng. Ví API chỉ ký lệnh đặt và lệnh hủy; dùng khóa riêng cho từng hệ thống.
  2. Phát lại nonce: không bao giờ dùng lại nonce. Theo dõi nonce off-chain và tăng một cách nguyên tử.
  3. Domain: luôn ký với chain ID 999 trên mạng chính (998 trên testnet), và đối chiếu separator bạn tính được với bảng ở trên.
  4. Kiểm chứng những gì bạn ký: gọi POST /v1/actions/{action}/typed-data và so sánh với bộ mã hóa của bạn trước khi ký bằng ví phần cứng.
  5. Xác minh on-chain là quyết định cuối cùng: API kiểm tra trước chữ ký, nhưng Account xác minh lại mọi directive trên on-chain. Không coi phản hồi xác nhận từ API là đã thực thi.
  6. Manager và ví API: manager kiểm soát quyền sở hữu, ví API và việc chuyển tài sản. Ví API chỉ ký thông điệp giao dịch. Hãy dùng khóa riêng biệt.

Tài liệu tham khảo​