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:
- 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. - 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. - 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):
| Byte | Trường | Ý nghĩa |
|---|---|---|
| 20 | account | Địa chỉ Account (address) |
| 8 | nonce | Nonce của người ký (uint64) |
| 1 | version | Nhóm hành động |
| 3 | id | ID hành động trong nhóm |
| phần còn lại | data | abi.encode của struct hành động bên trong |
| Version | Nhóm | ID hành động |
|---|---|---|
0 | HyperCall (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. |
1 | HyperLiquid (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 |
255 | System | 1 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.
| Domain | name | version | Người ký | Chuỗi | Separator |
|---|---|---|---|---|---|
| Ví API | HypercallApiSign | 1 | Ví API | 999 | 0x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb |
| Ví API | HypercallApiSign | 1 | Ví API | 998 | 0x339bee4c00da9a5361f687797205c8d03f323659f5d9dc9e0505b9437ddee25e |
| Manager | HypercallManagerSign | 1 | Manager | 999 | 0xc9b5b0b8b0d9d7ba716326acbf795cfe431ef960a25a8f958d6569bea2f1516e |
| Manager | HypercallManagerSign | 1 | Manager | 998 | 0xd1f76b6138be892c14b71b0569bdb049cb44f239d34c78ef1ffaacd2466f9f18 |
| RSM | HypercallRsmSign | 1 | Người ký RSM | 999 | 0x3d0cae2af623c614099dbadd67a1e1457fabde576aa270a70a57e39bf338a7be |
| RSM | HypercallRsmSign | 1 | Người ký RSM | 998 | 0x650b282053fb61d3fd477bdc28f6434311fe905e27cc4ca643e87e802c45938c |
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ệp | Domain | Người ký | Gửi tới | Thực thi |
|---|---|---|---|---|
HLOrder | API | Ví API | POST /v1/tee-perp/orders/submit, hoặc POST /v1/actions/hl_limit_order | Lệnh giới hạn Hyperliquid |
HLCancel | API | Ví API | POST /v1/tee-perp/cancels/submit-by-oid, hoặc POST /v1/actions/hl_cancel_by_oid | Hủy theo oid |
HLCancelByCloid | API | Ví API | POST /v1/tee-perp/cancels/submit, hoặc POST /v1/actions/hl_cancel_by_cloid | Hủy theo cloid |
HCPerpTriggerOrder | API | Ví API | POST /v1/tee-perp/orders/submit-trigger | Lệnh kích hoạt gốc (chỉ TEE) |
HCPerpOrderBatch | API | Ví API | POST /v1/tee-perp/orders/submit-batch | Lô lệnh gốc (chỉ TEE) |
HCPerpLeverageChange | API | Ví API | POST /v1/tee-perp/leverage/submit | Cập nhật đòn bẩy (chỉ TEE) |
HCPerpScheduleCancel | API | Ví API | POST /v1/tee-perp/schedule-cancel/submit | Công tắc dead-man (chỉ TEE) |
HCUpdateApiWallet | Manager | Manager | POST /v1/actions/hc_update_api_wallet | Sổ đăng ký ví API của Account |
HLAddApiWallet | Manager | Manager | POST /v1/actions/hl_add_api_wallet | Phê duyệt ví API trên HyperCore |
HLSendAsset | Manager | Manager | POST /v1/actions/hl_send_asset | sendAsset trên HyperCore từ Account |
HLSetAbstraction | Manager | Manager | POST /v1/actions/hl_set_abstraction | Chế độ tài khoản HyperCore (chỉ unified) |
HCTransferOption | Manager | Manager | Không được chấp nhận | Dành riêng, bị từ chối on-chain |
HLOrder, HLCancel, HLCancelByCloid, HLSendAsset | RSM | Người ký RSM | Chỉ sequencer | Lệnh phục hồi và sweep thông qua Account |
System* | RSM | Người ký RSM | Chỉ sequencer | Ghi 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
noncevà mọi trườnguint64,uint128hoặcuint256là số nguyên JSON tối đa9007199254740991, hoặc chuỗi thập phân. Dùng chuỗi cho giá trị lớn hơn mức đó.signaturelà chuỗi hex0xdài 65 byte (r || s || v).vcó thể là0,1,27hoặc28.- Các trường
bytes32là 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
1e8của HyperCore, ví dụ$50,000là5000000000000và0.001coin 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/marketsliệ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ân1e8.reduceOnly:truenế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ước | Giá trị |
|---|---|
| Typehash | 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd |
| Hash struct hành động | 0x0fd024c6bf8f132123e63a78d50008d8c39c52e5409ef6ca87a4eec8f6eabb41 |
| Hash struct directive | 0xd32948ee1f249b96124a6acdb5845d09aad8228512098598de6858d5484fe703 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85 |
| Hash struct hành động | 0xa34e7bb8af0d099f9c48095924e53067bcb9b542a816445b96abebbc5646b727 |
| Hash struct directive | 0x69d560ba5ef3e88459bde7fb8252e55dbc33627373c8f0cfcf8ef0868f59e097 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5 |
| Hash struct hành động | 0xfa4ab6440f946a6e279d90972d71223c768c01c8a91dc22703a6448dbcb966d0 |
| Hash struct directive | 0x998efb01bb9c842eea80e8cc084b9e4e7ec13b2111790e1acbfec32e49060d9d |
| 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ước | Giá trị |
|---|---|
| Typehash | 0x2d3104ab255275839aad254429e4be789f64a8d16b8e3e7d5f30a0db3c887b5c |
| Hash struct hành động | 0x285b3186be219b92d7159419288c0dce9bc4ad7bfc9536e009ebf24bd67f434c |
| Hash struct directive | 0xaa03e40b34b15e7e932ae827921930e7538387b596ef1040dbcc791e69021299 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0x9d4f467a44f4b0d39f234f3b91888546ce31dcbb67ce791550901b9042c38f8b |
| Hash mảng lệnh | 0x13fc75fcc69bf3b4ef7cdc3a0872c3cc1cf59440c74d366055109b6bd5ea7c98 |
| Hash struct directive | 0x69d0b1131e386769823fe1ab3facbe8e6fc013f86a117cf95cb52b8ce2f274e0 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0xe13845f0e6c16a5e1fc56b2d11fb0972faa2ec30b01e94d58c72147fa9b6a463 |
| Hash struct hành động | 0x0e6e271dd56192d7fb1f37ea2eaffecfbbe2d1f79cac78dce6a6930bb8cc253e |
| Hash struct directive | 0xe04b169bbb0e20042308e5aad1036ce60eda75f484a4d6093dc60f2c2231129e |
| 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ước | Giá trị |
|---|---|
| Typehash | 0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb |
| Hash struct hành động | 0x0a3ebfe48ef28a79beeee4d56e524f8a5280c38562efb697e7b1d63b3d475afc |
| Hash struct directive | 0xae64a13943a6a35b33aeb3095763b855c58c2119daf71e1e3228d8acf2645e8b |
| 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ước | Giá trị |
|---|---|
| Typehash | 0x8ebe7d19374200e5dc3ae838db74b370da95bd2b3a8aec9de85d2398dd4a9257 |
| Hash struct hành động | 0x8b6c4a9db102e9d27c9a4069b39ba35e04948129359f0c15cd5103dd101ffce7 |
| Hash struct directive | 0x830e291835ad182f290bc3d2bff09eaf9fd33acfbe44c6ad583218cd1a8232e5 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0x71c0e0dfbddc3456015249946354324befde42b6851d1c9b26c6a29f2e0b1ac2 |
| Hash struct hành động | 0xed32a441b0ee59c0252f5dff3411766289c9c35c19e3152b0b2b204176c2c7cd |
| Hash struct directive | 0xb990a3dfb4e8d96243539f8758b3a55249b217542bb4112f4f88ed67ec516ed9 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595 |
| Hash struct hành động | 0x9b8c0290da19ea1069e14833023c4621a4f043354b36b4f17d4803b1fce6e656 |
| Hash struct directive | 0xa0cb8a72188a61289fc2685c29a424605e0a2ee7b7af3e8cfee10e1c75153e08 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0xcf5fddf081e5f2a9a45aa87cb1a3c42e5aa20164566b1ad2369b6b1318eac786 |
| Hash struct hành động | 0xef6c70a3c14b9e77c710c6b3b3ee681ca270ef884bd8a64fa4064a96f3dda84e |
| Hash struct directive | 0xdda9d0fe82b63c728c4ac42585d5998a04cabaed0f957a2cafdf31a754829c3d |
| 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ệp | Typehash | Ràng buộc do Account áp dụng |
|---|---|---|
HLOrder | 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd | encodedTif 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 |
HLCancel | 0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85 | Không có |
HLCancelByCloid | 0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5 | Không có |
HLSendAsset | 0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595 | destination phải là Exchange |
Test vector HLOrder RSM (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):
| Bước | Giá trị |
|---|---|
| Typehash | 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd |
| Hash struct hành động | 0x39b4e0699f382aaad23f04740034e7c5581ba918139d2db63fbf586cc447e7db |
| Hash struct directive | 0xe6dde5ad6d310b5ebb83c09ec28ee5568700473b885bb483b7437dca202af4f3 |
| 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>(...).
| Wrapper | Kiểu bên trong | Typehash |
|---|---|---|
SystemCreditToken | CreditToken(uint32 srcDex,uint32 dstDex,uint64 token,uint64 amountWei) | 0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052 |
SystemCreditOption | CreditOption(bytes32 underlying,uint256 expiry,uint256 strike,bool isCall,uint256 amountWei) | 0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae |
SystemStartLiquidation | StartLiquidation(int256 equity,uint256 marginNeeded) | 0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e |
SystemStopLiquidation | StopLiquidation(uint256 startTime) | 0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3 |
SystemWithdrawToken | WithdrawToken(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.
amountWeiphả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.
underlyinglà một wordShortStringcủa OpenZeppelin: ASCII căn trái với độ dài byte ở byte cuối cùng (BTClà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.
marginNeededphải khác không. - SystemStopLiquidation yêu cầu
startTimebằ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,dstDexlà0hoặc4294967295,token = 0(USDC), vàamountWeilà 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ước | Giá trị |
|---|---|
| Typehash | 0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052 |
| Hash struct hành động | 0xc69d7c6e5c36c9789d990c6316eaff3be43980583806f41f8a8e6461b7114011 |
| Hash struct directive | 0x7ffa37cef7e08d3a2dd5501a8648899d37bc09ebb25d148c124e12c5047476e1 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae |
| Hash struct hành động | 0x4a8b563fc94d26c1da376145d5aa5d05f996232fcf9739ed0a662650e91861b6 |
| Hash struct directive | 0x190b638f1a462469bf0d070248acfc86bbbb95ea8a9d3d97d33581c7d6bb5554 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e |
| Hash struct hành động | 0x4cd6a7f0997eba84ef82eabd429a0d9ca80e55bd6d89d2e67eda9970d87ec803 |
| Hash struct directive | 0x84f18dc2577978d7890c9eb269fd787d99de37039b3a08e24745398feffbd0c5 |
| 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ước | Giá trị |
|---|---|
| Typehash | 0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3 |
| Hash struct hành động | 0x1d900a795b328bd5fa734bd6d7f74634b98ca66eb5e45322fb1ba6400564b62b |
| Hash struct directive | 0x977b9becdd26830f2cdf70ab40f72f24490fe6ed45822d1fc8c84120e9a46f40 |
| Digest cần ký | 0xbe65f82782b14dba42e334e32dd7dcc6bf14c96824523723a186a7381f8f12af |
Vector dùng startTime: 1760000000.
Test vector SystemWithdrawToken (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chuỗi 999):
| Bước | Giá trị |
|---|---|
| Typehash | 0x634b866e9a922bb846e297973c7a456e641b88f4e97493da9b222084d799c883 |
| Hash struct hành động | 0x10bd8d4372a09e613a6b4fb7018fcccde857ebf6cc3327d6c9a3c0f81515a076 |
| Hash struct directive | 0x86680427965513c65a7a170730b9f4fb2e2b40e22cd18338cb004b6a7872ada2 |
| 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ớiAccount__NonceAlreadyUsedkhi 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ý
- Off-chain: người ký xây dựng digest EIP-712 (
0x1901 || domainSeparator || structHash) và ký nó. - 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.
- Sequencer: gửi
Exchange.executeUserDirective(directive, signature). Exchange kiểm tra Account tồn tại và chuyển tiếp tớiAccount.executeUserDirective. - 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.
- 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
Processorvà cách mã hóa thông điệp ActionCaster đã bị loại bỏ trong Exchange0.2.0(tháng 2 năm 2026). Directive của Account hiện đi quaExchange.executeUserDirectivevà CoreWriter. Exchange0.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,rsmCommandRebalancevà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 |
HLRequestCancelByCloid | HLCancelByCloid 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 |
HCActionWithdrawToken | SystemWithdrawToken do RSM ký, được sequencer thực thi sau khi engine phê duyệt lệnh rút |
HCActionWithdrawOption | Ghi có quyền chọn là SystemCreditOption của RSM; nạp tiền dùng depositOption |
RsmCommandRebalance | HLOrder do RSM ký (IOC chỉ giảm vị thế) |
RsmCommandRepay | HLSendAsset do RSM ký gửi tới Exchange |
- Các hàm lệnh cũ.
placeCoreOrders,cancelCoreOrdersvàcancelCoreOrdersByCloiddùng cách mã hóa MsgPack và domainCoreSignatures("Exchange", chain ID1337). Chúng đã bị loại bỏ. nextNonce. Bộ đếm on-chainnextNonce[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
- 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.
- 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ử.
- Domain: luôn ký với chain ID
999trên mạng chính (998trên testnet), và đối chiếu separator bạn tính được với bảng ở trên. - Kiểm chứng những gì bạn ký: gọi
POST /v1/actions/{action}/typed-datavà so sánh với bộ mã hóa của bạn trước khi ký bằng ví phần cứng. - 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.
- 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
- Bắt đầu sử dụng để tạo Account và thiết lập ví API
- Tổng quan hợp đồng để xem địa chỉ đã triển khai và các loại directive
- Perps để xem luồng lệnh perp
- Xác thực & Ký để ký lệnh quyền chọn