Подпись EIP-712
Эта страница содержит справочник на уровне полей по каждому сообщению EIP-712, которое проверяет Hypercall: три домена подписи директив (API-кошелёк, Manager, RSM), сообщения для перпов, существующие только off-chain и использующие домен API-кошелька, а также отдельный домен Physical Covered Call Quote. Ордера на опционы через REST API используют другой домен, Hypercall; см. Аутентификация и подпись.
Всё описанное здесь сверено с контрактами, развёрнутыми в основной сети HyperEVM (chain ID 999): Exchange 0.6.1 по адресу 0xE6b7FaA216cabb2b38B392f577C9c826378b2240 и Account 0.2.4. Приведённые ниже разделители доменов и typehash зашиты в развёрнутый байткод.
Обзор
Директива представляет собой одно действие над одним Account. Она подписывается off-chain и отправляется on-chain секвенсором Hypercall через Exchange.executeUserDirective или Exchange.executeRsmDirective. Account восстанавливает подписанта из дайджеста EIP-712 и проверяет его полномочия:
- API-кошелёк: адрес, зарегистрированный на Account через
hc_update_api_wallet(Account.isApiWalletActive). Подписывает ордера и отмены. - Manager: владелец Account (
Account.manager). Подписывает изменения API-кошельков, переводы активов и смену режима аккаунта. - RSM-подписант: контролируется протоколом (
Exchange.rsmSigner). Подписывает зачисления, выводы средств, директивы ликвидации и восстановительные ордера reduce-only. Пользователи их никогда не подписывают.
Кодирование директивы
On-chain директива имеет вид abi.encodePacked(account, nonce, version, id, data):
| Байты | Поле | Значение |
|---|---|---|
| 20 | account | Адрес Account (address) |
| 8 | nonce | Nonce подписанта (uint64) |
| 1 | version | Семейство действий |
| 3 | id | ID действия внутри семейства |
| остаток | data | abi.encode вложенной структуры действия |
| Версия | Семейство | ID действий |
|---|---|---|
0 | HyperCall (HC) | 2 обновление API-кошелька. 1 (перевод опциона) зарезервирован и отклоняется. |
1 | HyperLiquid (HL) | 1 лимитный ордер, 9 добавление API-кошелька, 10 отмена по oid, 11 отмена по cloid, 13 перевод актива, 16 установка абстракции |
255 | System | 1 зачисление токена, 2 зачисление опциона, 3 запуск ликвидации, 4 остановка ликвидации, 5 вывод токена |
Собирать эту байтовую строку самостоятельно не нужно. Подпишите типизированные данные и отправьте в API account, nonce, action и signature, а API закодирует директиву.
Структура типизированных данных
Все директивы имеют одинаковую внешнюю структуру: адрес Account, nonce подписанта и одна вложенная структура действия.
<Outer>(address account,uint64 nonce,<Inner> action)<Inner>(...)
К строке внешнего типа дописывается определение вложенного типа, поэтому typehash покрывает оба. В терминах EIP-712 primaryType содержит внешнее имя, types содержит обе записи, а message имеет вид { account, nonce, action }. Порядок полей входит в строку типа и должен совпадать в точности.
Неподписываемые точки входа для пополнения
Не каждый вызов пополнения является действием EIP-712. Следующие методы вызываются прямыми транзакциями от плательщика или роутера:
function depositUsdcFor(address account, uint256 amount) external;
function depositOption(address account, address token, uint256 amount) external;
depositUsdcFor намеренно не требует подписи, поскольку msg.sender лишь платит USDC. Зачисление получает аккаунт Hypercall, явно указанный в аргументе account и в поле события UsdcDeposit.account. Этот метод могут вызывать роутеры и zap-контракты, поэтому индексаторы и бэкенд-сервисы не должны использовать msg.sender для определения получателя зачисления.
depositOption сжигает опционные токены у msg.sender и эмитирует Deposit(account, msg.sender, token, amount) для индексатора RSM. Зачисление опционов управляется событиями и не требует от вносящего подписи manager, агента или RSM.
Отдельный домен: котировки физически поставляемых покрытых колл-опционов
Котировки физически поставляемых покрытых колл-опционов проверяет фабрика, развёрнутая в выбранной сети. Они не используют верификатор Exchange и его домен с нулевым адресом.
Домен:
{
"name": "Hypercall Physical Covered Call",
"version": "1",
"chainId": "<selected chain id>",
"verifyingContract": "<exact PhysicalCoveredCallFactory address>"
}
Подписант: маркетмейкер, указанный в PhysicalCoveredCallQuote.marketMaker.
Канонические вложенные типы:
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)
Перед восстановлением подписанта котировки фабрика заново вычисляет requestHash из полного вложенного запроса. Таким образом, подпись фиксирует продавца, обёртку базового актива, количество долей обёртки, страйк, экспирацию, премию, срок действия котировки, nonce, chain id и адрес фабрики. Токен расчёта и его decimals задаются конфигурацией фабрики и не подписываются отдельно. В этом поколении без оракулов Pyth не используется. При фондировании продавцом хранилища расходуются и дайджест котировки, и nonce маркетмейкера.
Отправить подписанную котировку может только продавец, указанный в запросе. При фондировании NFT права требования райтера выпускается продавцу, а NFT длинной позиции по опциону выпускается маркетмейкеру из котировки, при условии что тот является допустимым получателем, когда включён необязательный allowlist покупателей. Валидная подпись разрешает фондирование, но не исполнение.
Исполнить опцион может только текущий владелец NFT длинной позиции. Это правило исключает ситуацию, когда оператор ERC-721 расходует allowance владельца на токен расчёта. Одобренный оператор по-прежнему может передать NFT по стандартным правилам ERC-721, тем самым передав экономическое право допустимому получателю, пока включён фильтр покупателей. При успешном исполнении у вызывающего владельца списываются денежные средства в размере страйка, ему поставляется базовый актив, а NFT длинной позиции сжигается.
Разделители доменов EIP-712
Три домена директив имеют одинаковую структуру и различаются только полем name. verifyingContract равен нулевому адресу, поэтому одна и та же подпись валидна для любого Account в сети, а привязку к конкретному Account обеспечивает адрес Account внутри сообщения.
{
"name": "<DomainName>",
"version": "1",
"chainId": <chainId>,
"verifyingContract": "0x0000000000000000000000000000000000000000"
}
Тип домена: EIP712Domain(string name,string version,uint256 chainId,address verifyingContract).
Chain ID: основная сеть 999, тестнет 998. Account выбирает разделитель по сети, в которой работает, поэтому подпись из тестнета никогда не пройдёт проверку в основной сети.
| Домен | name | version | Подписант | Сеть | Разделитель |
|---|---|---|---|---|---|
| API-кошелёк | HypercallApiSign | 1 | API-кошелёк | 999 | 0x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb |
| API-кошелёк | HypercallApiSign | 1 | API-кошелёк | 998 | 0x339bee4c00da9a5361f687797205c8d03f323659f5d9dc9e0505b9437ddee25e |
| Manager | HypercallManagerSign | 1 | Manager | 999 | 0xc9b5b0b8b0d9d7ba716326acbf795cfe431ef960a25a8f958d6569bea2f1516e |
| Manager | HypercallManagerSign | 1 | Manager | 998 | 0xd1f76b6138be892c14b71b0569bdb049cb44f239d34c78ef1ffaacd2466f9f18 |
| RSM | HypercallRsmSign | 1 | RSM-подписант | 999 | 0x3d0cae2af623c614099dbadd67a1e1457fabde576aa270a70a57e39bf338a7be |
| RSM | HypercallRsmSign | 1 | RSM-подписант | 998 | 0x650b282053fb61d3fd477bdc28f6434311fe905e27cc4ca643e87e802c45938c |
Прежде чем что-либо подписывать, вычислите разделитель самостоятельно и сравните:
import { ethers } from "ethers";
const separator = ethers.TypedDataEncoder.hashDomain({
name: "HypercallApiSign",
version: "1",
chainId: 999,
verifyingContract: ethers.ZeroAddress
});
// 0x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb
Справочник сообщений
Матрица подписантов и эндпоинтов
| Сообщение | Домен | Подписант | Куда отправлять | Что исполняет |
|---|---|---|---|---|
HLOrder | API | API-кошелёк | POST /v1/tee-perp/orders/submit или POST /v1/actions/hl_limit_order | Лимитный ордер Hyperliquid |
HLCancel | API | API-кошелёк | POST /v1/tee-perp/cancels/submit-by-oid или POST /v1/actions/hl_cancel_by_oid | Отмена по oid |
HLCancelByCloid | API | API-кошелёк | POST /v1/tee-perp/cancels/submit или POST /v1/actions/hl_cancel_by_cloid | Отмена по cloid |
HCPerpTriggerOrder | API | API-кошелёк | POST /v1/tee-perp/orders/submit-trigger | Нативный триггерный ордер (только TEE) |
HCPerpOrderBatch | API | API-кошелёк | POST /v1/tee-perp/orders/submit-batch | Нативный пакет ордеров (только TEE) |
HCPerpLeverageChange | API | API-кошелёк | POST /v1/tee-perp/leverage/submit | Изменение кредитного плеча (только TEE) |
HCPerpScheduleCancel | API | API-кошелёк | POST /v1/tee-perp/schedule-cancel/submit | Dead-man switch (только TEE) |
HCUpdateApiWallet | Manager | Manager | POST /v1/actions/hc_update_api_wallet | Реестр API-кошельков Account |
HLAddApiWallet | Manager | Manager | POST /v1/actions/hl_add_api_wallet | Одобрение API-кошелька в HyperCore |
HLSendAsset | Manager | Manager | POST /v1/actions/hl_send_asset | sendAsset в HyperCore с Account |
HLSetAbstraction | Manager | Manager | POST /v1/actions/hl_set_abstraction | Режим аккаунта HyperCore (только unified) |
HCTransferOption | Manager | Manager | Не принимается | Зарезервировано, отклоняется on-chain |
HLOrder, HLCancel, HLCancelByCloid, HLSendAsset | RSM | RSM-подписант | Только секвенсор | Восстановительные ордера и свипы через Account |
System* | RSM | RSM-подписант | Только секвенсор | Зачисления, выводы, ликвидация через Exchange |
Все маршруты /v1/actions/{action} принимают account, nonce, action и signature. POST /v1/actions/{action}/typed-data возвращает точные типизированные данные для подписи данного запроса, и это самый простой способ проверить ваш кодировщик. GET /v1/directives/{directive_id} возвращает результат on-chain. Схемы запросов приведены в справочнике API.
Соглашения по формату передачи
nonceи все поляuint64,uint128илиuint256передаются как целые числа JSON до9007199254740991либо как десятичные строки. Для больших значений используйте строки.signatureпредставляет собой 65-байтовую hex-строку с префиксом0x(r || s || v).vможет быть0,1,27или28.- Поля
bytes32передаются как 32-байтовый hex с префиксом0x. Адреса указываются в checksum-формате или в нижнем регистре. - Цены и размеры для перпов задаются целыми числами HyperCore с множителем
1e8, например$50,000соответствует5000000000000, а0.001монеты соответствует100000.
Директивы API-кошелька (HypercallApiSign)
Подписываются активным API-кошельком Account. Используйте chain ID 999 и name HypercallApiSign.
В тестовых векторах используются аккаунт-заглушка и фиксированный nonce, чтобы вы могли побайтно проверить свой кодировщик. Дайджест равен keccak256(0x1901 || domainSeparator || directiveStructHash).
HLOrder
Один лимитный ордер Hyperliquid для Account.
Структура:
struct LimitOrder {
uint32 asset;
bool isBuy;
uint64 limitPx;
uint64 sz;
bool reduceOnly;
uint8 encodedTif;
uint128 cloid;
}
struct HLOrder {
address account;
uint64 nonce;
LimitOrder action;
}
Канонический тип EIP-712:
HLOrder(address account,uint64 nonce,LimitOrder action)LimitOrder(uint32 asset,bool isBuy,uint64 limitPx,uint64 sz,bool reduceOnly,uint8 encodedTif,uint128 cloid)
Typehash: 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd. Подписант: API-кошелёк. Действие: версия 1, id 1.
asset: индекс актива Hyperliquid.GET /v1/tee-perp/marketsвозвращает список рынков перпов, которые принимает Hypercall, и их индексы.isBuy:trueдля покупки,falseдля продажи.limitPx,sz: цена и размер, умноженные на1e8.reduceOnly:true, если ордер может только сокращать позицию.encodedTif: ALO =1, GTC =2, IOC =3. Любое другое значение отклоняется.cloid: клиентский ID ордера, ненулевой. Используется впоследствии для отмены по cloid.
Пример (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);
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd |
| Хеш структуры действия | 0x0fd024c6bf8f132123e63a78d50008d8c39c52e5409ef6ca87a4eec8f6eabb41 |
| Хеш структуры директивы | 0xd32948ee1f249b96124a6acdb5845d09aad8228512098598de6858d5484fe703 |
| Дайджест для подписи | 0xc3c42699092fe20c7dbc4205a1027f55c28d33a682a64bd3f04e40f1d28693f5 |
В тестовом векторе используются isBuy: true, limitPx: 5000000000000, sz: 100000, reduceOnly: false, encodedTif: 2, asset: 0 и cloid, равный nonce.
Отправка: POST /v1/tee-perp/orders/submit с полями account, nonce, action и signature. Hypercall выполняет проверку маржи, после чего защищённый анклав подписывает и отправляет нативный ордер Hyperliquid с прикреплённым builder code Hypercall. Предварительно manager аккаунта должен одобрить этого билдера через Account.approveZeroFeeBuilder; см. Онбординг. Полный процесс описан в разделе Перпы.
{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 1760000000000,
"action": {
"asset": 0,
"isBuy": true,
"limitPx": "5000000000000",
"sz": "100000",
"reduceOnly": false,
"encodedTif": 2,
"cloid": "1760000000000"
},
"signature": "0x<65 byte signature>"
}
То же подписанное сообщение принимается и на POST /v1/actions/hl_limit_order: в этом случае оно кодируется в on-chain директиву, которая исполняется через Exchange.executeUserDirective и Account.performCoreAction.
HLCancel
Отменяет один ордер по ID ордера Hyperliquid. Обёртка называется HLCancel, вложенная структура 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. Подписант: API-кошелёк. Действие: версия 1, id 10. Отправка: POST /v1/tee-perp/cancels/submit-by-oid или 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);
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85 |
| Хеш структуры действия | 0xa34e7bb8af0d099f9c48095924e53067bcb9b542a816445b96abebbc5646b727 |
| Хеш структуры директивы | 0x69d560ba5ef3e88459bde7fb8252e55dbc33627373c8f0cfcf8ef0868f59e097 |
| Дайджест для подписи | 0x5046aba9fb33c55ce736faf63734ea66914f3f168ff0aff2229fa6f31fa9b330 |
В тестовом векторе используются asset: 0 и oid: 123456789.
HLCancelByCloid
Отменяет один ордер по клиентскому ID, заданному в 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. Подписант: API-кошелёк. Действие: версия 1, id 11. Отправка: POST /v1/tee-perp/cancels/submit или 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);
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5 |
| Хеш структуры действия | 0xfa4ab6440f946a6e279d90972d71223c768c01c8a91dc22703a6448dbcb966d0 |
| Хеш структуры директивы | 0x998efb01bb9c842eea80e8cc084b9e4e7ec13b2111790e1acbfec32e49060d9d |
| Дайджест для подписи | 0x56af82a6aa7fa50907a23c6cfe3aa556af5aa087b1157163ebf6ea0240e8d29d |
В тестовом векторе используются asset: 0 и cloid: 1760000000000.
Сообщения для перпов, доступные только через TEE
Эти четыре сообщения проверяет API Hypercall, а не контракт Account, поскольку анклав исполняет их нативно на Hyperliquid и on-chain директив для них не существует. Они используют тот же домен HypercallApiSign и ту же авторизацию API-кошелька, что и HLOrder (подписант должен быть активным API-кошельком Account, а Account должен работать в режиме портфельной маржи). Их typehash отсутствуют в контрактах. Nonce задаётся как Unix-время в миллисекундах.
PerpOrderTerms
Эту структуру встраивают и HCPerpTriggerOrder, и HCPerpOrderBatch. Лимитный дочерний ордер подписывает свой байт TIF с triggerPx = 0, isMarket = false, tpsl = 0. Триггерный дочерний ордер подписывает encodedTif = 0, положительный triggerPx и tpsl, равный 1 (тейк-профит) или 2 (стоп-лосс).
struct PerpOrderTerms {
uint32 asset;
bool isBuy;
uint64 limitPx;
uint64 sz;
bool reduceOnly;
uint8 encodedTif;
uint64 triggerPx;
bool isMarket;
uint8 tpsl;
uint128 cloid;
}
HCPerpTriggerOrder
Один ордер стоп-лосс или тейк-профит, отправляется на POST /v1/tee-perp/orders/submit-trigger. Поле action.orderType в запросе должно быть триггерным.
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
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x2d3104ab255275839aad254429e4be789f64a8d16b8e3e7d5f30a0db3c887b5c |
| Хеш структуры действия | 0x285b3186be219b92d7159419288c0dce9bc4ad7bfc9536e009ebf24bd67f434c |
| Хеш структуры директивы | 0xaa03e40b34b15e7e932ae827921930e7538387b596ef1040dbcc791e69021299 |
| Дайджест для подписи | 0xc46aadc390b66c235af15e199e188ab23fb7f7f1b9237f6c2849c264c28d94da |
Тестовый вектор описывает рыночный стоп-лосс на продажу с reduce-only: asset: 0, isBuy: false, limitPx: 4800000000000 (худшая допустимая цена), sz: 100000, reduceOnly: true, encodedTif: 0, triggerPx: 4900000000000, isMarket: true, tpsl: 2, cloid: 1760000000001.
HCPerpOrderBatch
До 100 ордеров в рамках одной группировки, отправляется на POST /v1/tee-perp/orders/submit-batch. У каждого ордера должен быть уникальный cloid. grouping принимает значения 0 (без группировки), 1 (normalTpsl) или 2 (positionTpsl). Пакет учитывается в лимите запросов как одна постановка ордера.
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. Массив orders кодируется как keccak256 от конкатенации хешей структур PerpOrderTerms в порядке отправки.
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x9d4f467a44f4b0d39f234f3b91888546ce31dcbb67ce791550901b9042c38f8b |
| Хеш массива ордеров | 0x13fc75fcc69bf3b4ef7cdc3a0872c3cc1cf59440c74d366055109b6bd5ea7c98 |
| Хеш структуры директивы | 0x69d0b1131e386769823fe1ab3facbe8e6fc013f86a117cf95cb52b8ce2f274e0 |
| Дайджест для подписи | 0x4b5cd34b1f254fdd9881b7674a3412807e16cade1f2ccc7a1e261482682fbd07 |
Тестовый вектор использует grouping: 1 с двумя ордерами: лимитная покупка GTC (limitPx: 5000000000000, sz: 100000, cloid: 1760000000000), за которой следует стоп-лосс из примера с триггерным ордером.
HCPerpLeverageChange
Устанавливает кредитное плечо для одного актива, отправляется на POST /v1/tee-perp/leverage/submit. leverage должно быть больше нуля.
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
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0xe13845f0e6c16a5e1fc56b2d11fb0972faa2ec30b01e94d58c72147fa9b6a463 |
| Хеш структуры действия | 0x0e6e271dd56192d7fb1f37ea2eaffecfbbe2d1f79cac78dce6a6930bb8cc253e |
| Хеш структуры директивы | 0xe04b169bbb0e20042308e5aad1036ce60eda75f484a4d6093dc60f2c2231129e |
| Дайджест для подписи | 0xb2a43487152a7cecc73d2b6b84d817a58dd02c559b05289a8d8e1b5c3d25e266 |
Тестовый вектор устанавливает кросс-плечо 5x для asset: 0.
HCPerpScheduleCancel
Dead-man switch Hyperliquid: отмена всех открытых ордеров в момент time (Unix-время в миллисекундах, не менее чем на семь секунд вперёд). Отправляется на POST /v1/tee-perp/schedule-cancel/submit. Чтобы снять запланированную отмену, не передавайте time в запросе и подпишите time = 0. Явно переданный 0 отклоняется.
struct PerpScheduleCancel {
uint64 time;
}
struct HCPerpScheduleCancel {
address account;
uint64 nonce;
PerpScheduleCancel action;
}
HCPerpScheduleCancel(address account,uint64 nonce,PerpScheduleCancel action)PerpScheduleCancel(uint64 time)
Typehash: 0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb |
| Хеш структуры действия | 0x0a3ebfe48ef28a79beeee4d56e524f8a5280c38562efb697e7b1d63b3d475afc |
| Хеш структуры директивы | 0xae64a13943a6a35b33aeb3095763b855c58c2119daf71e1e3228d8acf2645e8b |
| Дайджест для подписи | 0xa01806f47299010b5963a516562be3c3b44fed4f4a9e2e56c4bb601630146cdc |
Тестовый вектор планирует отмену на time: 1760000060000.
Подготовленная отмена с подписью manager
POST /v1/tee-perp/cancels/submit-prepared реализует отмену с подписью manager. Структура типизированных данных здесь не используется. Manager подписывает дайджест подготовленной нативной отмены Hyperliquid, передаваемой как preparedRequest (base64), с managerSignature в канонической форме low-s, а также authenticationSignature с меткой времени, которая аутентифицирует кошелёк manager. Схема запроса приведена в справочнике API.
Директивы manager (HypercallManagerSign)
Подписываются manager аккаунта. Используйте chain ID 999 и name HypercallManagerSign. Account требует signer == manager. Отправка через POST /v1/actions/{action}.
HCUpdateApiWallet
Добавляет, заменяет или удаляет (addr = 0x0) API-кошелёк, хранящийся на Account под именем name.
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. Действие: версия 0, id 2. Отправка: POST /v1/actions/hc_update_api_wallet с action вида { "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);
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x8ebe7d19374200e5dc3ae838db74b370da95bd2b3a8aec9de85d2398dd4a9257 |
| Хеш структуры действия | 0x8b6c4a9db102e9d27c9a4069b39ba35e04948129359f0c15cd5103dd101ffce7 |
| Хеш структуры директивы | 0x830e291835ad182f290bc3d2bff09eaf9fd33acfbe44c6ad583218cd1a8232e5 |
| Дайджест для подписи | 0x06589077544af449314db1fa8c7aac2d277cce9e833a04992d88161ede24cbe8 |
В тестовом векторе используются name trading-bot (0x74726164696e672d626f74, дополненный нулями справа) и addr 0x2222222222222222222222222222222222222222. Полный процесс работы с API-кошельком описан в разделе Онбординг. Account эмитирует ApiWalletUpdated(name, addr).
HLAddApiWallet
Одобряет API-кошелёк Hyperliquid для Account в 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. Действие: версия 1, id 9. Отправка: POST /v1/actions/hl_add_api_wallet.
apiWalletName имеет тип string, поэтому в структуре его поле равно keccak256(bytes(apiWalletName)). Ethers и viem делают это автоматически.
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x71c0e0dfbddc3456015249946354324befde42b6851d1c9b26c6a29f2e0b1ac2 |
| Хеш структуры действия | 0xed32a441b0ee59c0252f5dff3411766289c9c35c19e3152b0b2b204176c2c7cd |
| Хеш структуры директивы | 0xb990a3dfb4e8d96243539f8758b3a55249b217542bb4112f4f88ed67ec516ed9 |
| Дайджест для подписи | 0x584886d020316085de0e0dec16331b8e990558be3e8fd004c47200abbebed518 |
В тестовом векторе используются apiWalletAddress 0x2222222222222222222222222222222222222222 и apiWalletName hl-bot.
HLSendAsset
Переводит активы с Account в HyperCore указанному получателю.
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. Действие: версия 1, id 13. Отправка: 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);
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595 |
| Хеш структуры действия | 0x9b8c0290da19ea1069e14833023c4621a4f043354b36b4f17d4803b1fce6e656 |
| Хеш структуры директивы | 0xa0cb8a72188a61289fc2685c29a424605e0a2ee7b7af3e8cfee10e1c75153e08 |
| Дайджест для подписи | 0x7c7037f27c659a1885f744778480e6847c5d08e98fb22517265ba708b6597d10 |
Тестовый вектор переводит 5 USDC (amountWei: 500000000) из перпов (srcDex: 0) на спот (dstDex: 4294967295), в качестве destination указан продакшн-Exchange 0xE6b7FaA216cabb2b38B392f577C9c826378b2240.
HLSetAbstraction
Устанавливает режим аккаунта HyperCore для Account. Account принимает только user, равный самому себе, и abstraction = 2 (unified account); всё остальное откатывается. Этот режим необходим для портфельной маржи.
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. Действие: версия 1, id 16. Отправка: POST /v1/actions/hl_set_abstraction.
Тестовый вектор (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0xcf5fddf081e5f2a9a45aa87cb1a3c42e5aa20164566b1ad2369b6b1318eac786 |
| Хеш структуры действия | 0xef6c70a3c14b9e77c710c6b3b3ee681ca270ef884bd8a64fa4064a96f3dda84e |
| Хеш структуры директивы | 0xdda9d0fe82b63c728c4ac42585d5998a04cabaed0f957a2cafdf31a754829c3d |
| Дайджест для подписи | 0xf49d7d8d74596e503d6a1bdfb26653533a12a5ba3816acd992d0bd4ef378f59d |
Тестовый вектор задаёт user равным Account и abstraction равным 2.
HCTransferOption (зарезервировано)
В контрактах определён HCTransferOption(address account,uint64 nonce,TransferOption action)TransferOption(address recipient,address option,uint256 amountWei) (typehash 0xa218e1158788b23987f954edc7a07659a03a03fe5ba981a5bbe44d7a146e0819, версия действия 0, id 1), но тип подписанта ему не назначен. Account откатывает его с Account__UserDirectiveNotSupported, а API отклоняет hc_transfer_option. Не подписывайте это сообщение. Для перемещения опционных токенов используйте depositOption и выводы.
Транзакции manager без подписи
Некоторые действия manager выполняются прямыми вызовами Account, а не сообщениями EIP-712: Account.approveZeroFeeBuilder(builder) одобряет билдера Hyperliquid с максимальной комиссией 0% и обязателен однократно перед первым ордером на перпы (см. Онбординг). Account.transferTo(recipient, token, amount) выводит токены с Account в HyperEVM. Оба вызова требуют msg.sender == manager и откатываются, пока Account находится в ликвидации.
Директивы RSM (HypercallRsmSign)
Подписываются RSM-подписантом и отправляются секвенсором. Они зачисляют депозиты, обрабатывают выводы, запускают и останавливают ликвидацию, а также выставляют восстановительные ордера IOC с reduce-only. Маркетмейкеры и пользователи их не подписывают и не отправляют; они описаны здесь, чтобы вы могли проверить, что протокол вправе делать с Account. Используйте chain ID 999 и name HypercallRsmSign. Exchange проверяет signer == rsmSigner (сейчас в основной сети это 0x502E7fAbF34E84EeB115C34FE947b79A94dF886E), а вызывающий должен иметь SEQUENCER_ROLE.
Ордера и свипы RSM (исполняются Account)
Они используют те же структуры HL в домене RSM, поэтому их typehash совпадают с typehash для API и manager, а отличается только разделитель домена. Account накладывает дополнительные ограничения и исполняет их даже во время ликвидации.
| Сообщение | Typehash | Ограничение, проверяемое Account |
|---|---|---|
HLOrder | 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd | encodedTif должен быть IOC (3), а ордер должен быть reduceOnly либо являться спотовой продажей в USDC (ID спотовых активов от 10000 до 99999) с лимитом не более чем на 5% ниже спотовой цены HyperCore |
HLCancel | 0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85 | Нет |
HLCancelByCloid | 0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5 | Нет |
HLSendAsset | 0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595 | destination должен быть Exchange |
Тестовый вектор RSM HLOrder (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd |
| Хеш структуры действия | 0x39b4e0699f382aaad23f04740034e7c5581ba918139d2db63fbf586cc447e7db |
| Хеш структуры директивы | 0xe6dde5ad6d310b5ebb83c09ec28ee5568700473b885bb483b7437dca202af4f3 |
| Дайджест для подписи | 0x57afa1e810804e768c05a467aa88ede15fdceedae5aaa840adff61a613aca469 |
Вектор RSM HLOrder описывает продажу IOC с reduce-only (isBuy: false, limitPx: 4800000000000, sz: 100000, reduceOnly: true, encodedTif: 3, cloid, равный nonce). Exchange.executeRsmDirective проверяет подпись и передаёт действие в Account.
Системные действия (исполняются Exchange)
Версия 255. Каждая обёртка имеет вид System<Action>(address account,uint64 nonce,<Action> action)<Action>(...).
| Обёртка | Вложенный тип | 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 |
Полные строки внешних типов:
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 зачисляет на Account спотовые или перп-токены из HyperCore.
amountWeiдолжен быть ненулевым, а Account должен быть активирован в HyperCore. - SystemCreditOption выпускает опционные токены на Account, при необходимости разворачивая опционную пару.
underlyingпредставляет собой слово OpenZeppelinShortString: ASCII с выравниванием по левому краю и длиной в байтах в последнем байте (BTCкодируется как0x42544300...03). Неканонические кодировки откатываются. - SystemStartLiquidation записывает параметры аукциона и блокирует Account.
marginNeededдолжен быть ненулевым. - SystemStopLiquidation требует, чтобы
startTimeсовпадал с записанным временем начала, и возвращает Account его manager. - SystemWithdrawToken ставит в очередь поставку Standard USDC в HyperCore с собственного баланса Exchange. Требуются
subAccount = 0,srcDex = 0,dstDex, равный0или4294967295,token = 0(USDC) иamountWei, кратный единице EVM. Квитанция HyperEVM сама по себе не подтверждает поставку в HyperCore.
Тестовый вектор SystemCreditToken (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052 |
| Хеш структуры действия | 0xc69d7c6e5c36c9789d990c6316eaff3be43980583806f41f8a8e6461b7114011 |
| Хеш структуры директивы | 0x7ffa37cef7e08d3a2dd5501a8648899d37bc09ebb25d148c124e12c5047476e1 |
| Дайджест для подписи | 0x95f75e5ddb4837de3f578b8aa0d714d4b02672b18c4929e3d2dda4a266de8254 |
Вектор зачисляет 5 USDC (srcDex и dstDex, равные 4294967295, token: 0, amountWei: 500000000).
Тестовый вектор SystemCreditOption (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae |
| Хеш структуры действия | 0x4a8b563fc94d26c1da376145d5aa5d05f996232fcf9739ed0a662650e91861b6 |
| Хеш структуры директивы | 0x190b638f1a462469bf0d070248acfc86bbbb95ea8a9d3d97d33581c7d6bb5554 |
| Дайджест для подписи | 0x86fb7c53bb7e139a4d5df7db2feae40e634efe09ea7509165d3cece75d75fce2 |
Вектор зачисляет один колл-опцион на BTC (underlying: 0x42544300...03, expiry: 1761811200, strike: 80000, isCall: true, amountWei: 1000000000000000000).
Тестовый вектор SystemStartLiquidation (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e |
| Хеш структуры действия | 0x4cd6a7f0997eba84ef82eabd429a0d9ca80e55bd6d89d2e67eda9970d87ec803 |
| Хеш структуры директивы | 0x84f18dc2577978d7890c9eb269fd787d99de37039b3a08e24745398feffbd0c5 |
| Дайджест для подписи | 0xcc72c0e7829938c9ca0a4515d759f94cc96d2f24cd51a134a430f215ed5f5d4b |
Вектор использует equity: -1500000000 и marginNeeded: 20000000000 (оба в USDC с шестью знаками после запятой).
Тестовый вектор SystemStopLiquidation (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3 |
| Хеш структуры действия | 0x1d900a795b328bd5fa734bd6d7f74634b98ca66eb5e45322fb1ba6400564b62b |
| Хеш структуры директивы | 0x977b9becdd26830f2cdf70ab40f72f24490fe6ed45822d1fc8c84120e9a46f40 |
| Дайджест для подписи | 0xbe65f82782b14dba42e334e32dd7dcc6bf14c96824523723a186a7381f8f12af |
Вектор использует startTime: 1760000000.
Тестовый вектор SystemWithdrawToken (аккаунт 0x1111111111111111111111111111111111111111, nonce 1760000000000, сеть 999):
| Шаг | Значение |
|---|---|
| Typehash | 0x634b866e9a922bb846e297973c7a456e641b88f4e97493da9b222084d799c883 |
| Хеш структуры действия | 0x10bd8d4372a09e613a6b4fb7018fcccde857ebf6cc3327d6c9a3c0f81515a076 |
| Хеш структуры директивы | 0x86680427965513c65a7a170730b9f4fb2e2b40e22cd18338cb004b6a7872ada2 |
| Дайджест для подписи | 0x65cc392038decb9ccdc23b0a4a1cfbe657d3417f8cd9ebf2319b3172fb7d885c |
Вектор выводит 5 USDC (amountWei: 500000000) на destination 0x1111111111111111111111111111111111111111 с srcDex: 0, dstDex: 0, token: 0.
Nonce
У каждого подписанта своё независимое пространство nonce, которое отслеживается в трёх местах.
- Контракт Account: битовая карта на каждого подписанта.
Account.isNonceUsed(signer, nonce)возвращает, был ли nonce использован. Пользовательская директива при повторном использовании nonce откатывается сAccount__NonceAlreadyUsed.nextNonceотсутствует; пропуски допустимы, и порядок on-chain не важен. - Контракт Exchange: битовая карта для RSM-подписанта, читается через
Exchange.isNonceUsed(signer, nonce). - Движок: хранит 100 наибольших nonce на каждого подписанта. Новый nonce не должен входить в этот набор, после заполнения набора должен превышать наименьший сохранённый nonce и должен строго укладываться в окно от двух суток до и одних суток после серверного времени в миллисекундах.
В качестве исходного значения nonce используйте текущее Unix-время в миллисекундах и увеличивайте его для каждого подписанта. Двум запросам, подписанным одним кошельком в одну и ту же миллисекунду, нужны разные nonce, поэтому ведите счётчик. Для маршрутов TEE-перпов nonce также служит временной привязкой запроса, поэтому используйте там реальные метки времени в миллисекундах, а не малые целые числа.
function isNonceUsed(address signer, uint256 nonce) external view returns (bool);
Процесс проверки подписи
- Off-chain: подписант формирует дайджест EIP-712 (
0x1901 || domainSeparator || structHash) и подписывает его. - API: Hypercall восстанавливает подписанта, проверяет, что это активный API-кошелёк или manager, для ордеров выполняет проверку маржи в движке, после чего ставит директиву в очередь. В ответе указываются фактическая стадия, детали отклонения и хеш транзакции.
- Секвенсор: отправляет
Exchange.executeUserDirective(directive, signature). Exchange проверяет существование Account и передаёт вызов вAccount.executeUserDirective. - Account: заново собирает дайджест из собственного адреса, nonce и действия, восстанавливает подписанта с разделителем API или manager для данного действия, проверяет полномочия, расходует nonce и исполняет действие. Действия HL уходят в CoreWriter HyperCore. Действия HC обновляют реестр API-кошельков.
- Клиент: опрашивает
GET /v1/directives/{directive_id}, чтобы получить итоговый статус.
Маршруты TEE-перпов завершаются после шага API: ордер на Hyperliquid исполняет анклав, а не Account.
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
Устаревшее и удалённое
Эти элементы присутствовали в прежних версиях страницы и больше не входят в развёрнутую систему. Они перечислены, чтобы интеграции, построенные на их основе, можно было перевести на актуальные механизмы.
- Кодирование Processor и ActionCaster. Контракт
Processorи кодирование сообщений ActionCaster удалены в Exchange0.2.0(февраль 2026). Директивы Account теперь проходят черезExchange.executeUserDirectiveи CoreWriter. В развёрнутом Exchange0.6.1старых точек входа нет. - Точки входа Exchange с собственными структурами.
hlRequestOrder,hlRequestCancel,hlRequestCancelByCloid,hlActionSendAsset,hcActionWithdrawToken,hcActionWithdrawOption,rsmCommandRebalanceиrsmCommandRepayудалены. Их замены:
| Удалённое сообщение | Замена |
|---|---|
HLRequestCancel (пакет HLCancel{asset,oid} плюс nonce) | HLCancel с одним CancelOrderByOid на директиву |
HLRequestCancelByCloid | HLCancelByCloid с одним CancelOrderByCloid на директиву |
HLActionSendAsset (account, nonce, destination, srcDex, dstDex, token, amountWei) | HLSendAsset со структурой SendAsset, в которую добавлен subAccount |
HCActionWithdrawToken | SystemWithdrawToken с подписью RSM, исполняемый секвенсором после одобрения вывода движком |
HCActionWithdrawOption | Зачисление опционов выполняется через RSM SystemCreditOption; депозиты через depositOption |
RsmCommandRebalance | HLOrder с подписью RSM (IOC с reduce-only) |
RsmCommandRepay | HLSendAsset с подписью RSM в адрес Exchange |
- Устаревшие функции ордеров.
placeCoreOrders,cancelCoreOrdersиcancelCoreOrdersByCloidиспользовали кодирование MsgPack и доменCoreSignatures("Exchange", chain ID1337). Они удалены. nextNonce. On-chain счётчикnextNonce[signer]больше не существует. Осталась только битовая карта использованных nonce (isNonceUsed).- Разделители основной сети с пометкой TBD. Ранее разделители manager и RSM для основной сети были помечены как TBD. Все три зафиксированы и приведены выше.
HCTransferOption. Определён, но так и не был включён; см. выше.
Соображения безопасности
- Ключи: храните ключ manager на аппаратном кошельке. API-кошельки подписывают только ордера и отмены; используйте отдельные ключи для каждой системы.
- Повторное использование nonce: никогда не используйте nonce повторно. Отслеживайте nonce off-chain и увеличивайте их атомарно.
- Домен: всегда подписывайте с chain ID
999в основной сети (998в тестнете) и сверяйте вычисленный разделитель с таблицей выше. - Проверяйте то, что подписываете: вызовите
POST /v1/actions/{action}/typed-dataи сравните результат с выводом вашего кодировщика до подписи на аппаратном кошельке. - Окончательна только on-chain проверка: API предварительно проверяет подписи, но Account повторно проверяет каждую директиву on-chain. Не считайте подтверждение от API фактом исполнения.
- Manager и API-кошелёк: manager контролирует владение, API-кошельки и перемещение активов. API-кошельки подписывают только торговые сообщения. Используйте разные ключи.
Ссылки
- Онбординг: создание Account и настройка API-кошелька
- Обзор контрактов: адреса развёрнутых контрактов и типы директив
- Перпы: процесс работы с ордерами на перпы
- Аутентификация и подпись: подпись ордеров на опционы