Assinatura EIP-712
Esta página é a referência, campo a campo, de toda mensagem EIP-712 que a Hypercall verifica: os três domínios de assinatura de diretivas (API wallet, Manager, RSM), as mensagens de perpétuos exclusivamente off-chain que compartilham o domínio da API wallet e o domínio avulso Physical Covered Call Quote. Ordens de opções na API REST usam um domínio diferente, Hypercall; consulte Autenticação e Assinatura.
Tudo aqui foi conferido com os contratos implantados na mainnet da HyperEVM (chain ID 999): Exchange 0.6.1 em 0xE6b7FaA216cabb2b38B392f577C9c826378b2240 e Account 0.2.4. Os separadores de domínio e typehashes abaixo estão embutidos nesse bytecode implantado.
Visão Geral
Uma diretiva é uma ação sobre uma Account, assinada off-chain e enviada on-chain pelo sequencer da Hypercall por meio de Exchange.executeUserDirective ou Exchange.executeRsmDirective. A Account recupera o signatário a partir do digest EIP-712 e verifica a autorização:
- API wallet: um endereço registrado na Account com
hc_update_api_wallet(Account.isApiWalletActive). Assina ordens e cancelamentos. - Manager: o dono da Account (
Account.manager). Assina alterações de API wallet, envios de ativos e mudanças de modo de conta. - Signatário RSM: controlado pelo protocolo (
Exchange.rsmSigner). Assina créditos, saques, diretivas de liquidação e ordens de recuperação reduce-only. Usuários nunca assinam essas mensagens.
Codificação da Diretiva
On-chain, uma diretiva é abi.encodePacked(account, nonce, version, id, data):
| Bytes | Campo | Significado |
|---|---|---|
| 20 | account | O endereço da Account (address) |
| 8 | nonce | O nonce do signatário (uint64) |
| 1 | version | Família da ação |
| 3 | id | ID da ação dentro da família |
| restante | data | abi.encode da struct interna da ação |
| Versão | Família | IDs de ação |
|---|---|---|
0 | HyperCall (HC) | 2 atualizar API wallet. 1 (transferir opção) é reservado e rejeitado. |
1 | HyperLiquid (HL) | 1 ordem limitada, 9 adicionar API wallet, 10 cancelar por oid, 11 cancelar por cloid, 13 enviar ativo, 16 definir abstraction |
255 | System | 1 creditar token, 2 creditar opção, 3 iniciar liquidação, 4 encerrar liquidação, 5 sacar token |
Você não monta essa sequência de bytes por conta própria. Assine os dados tipados e envie account, nonce, action e signature para a API, que codifica a diretiva.
Formato dos Dados Tipados
Toda diretiva tem o mesmo formato externo: o endereço da Account, o nonce do signatário e uma struct interna da ação.
<Outer>(address account,uint64 nonce,<Inner> action)<Inner>(...)
A string de tipo externa anexa a definição do tipo interno, então o typehash cobre ambos. Em termos de EIP-712, primaryType é o nome externo, types contém as duas entradas e message é { account, nonce, action }. A ordem dos campos faz parte da string de tipo e precisa coincidir exatamente.
Pontos de Entrada de Funding sem Assinatura
Nem toda chamada de funding é uma ação EIP-712. Estes métodos são transações diretas enviadas pela carteira pagadora ou pelo router:
function depositUsdcFor(address account, uint256 amount) external;
function depositOption(address account, address token, uint256 amount) external;
depositUsdcFor é intencionalmente sem assinatura porque msg.sender é apenas o pagador do USDC. A conta Hypercall creditada é o argumento explícito account e o campo UsdcDeposit.account do evento. Routers e zaps podem chamar esse método, então indexadores e serviços de backend não devem usar msg.sender para atribuir o crédito.
depositOption queima tokens de opção de msg.sender e emite Deposit(account, msg.sender, token, amount) para o indexador RSM. O caminho de crédito de opções é orientado a eventos e não usa assinatura de manager, agent ou RSM do depositante.
Domínio Avulso: Cotações de Covered Call com Entrega Física
Cotações de covered call com entrega física são verificadas pela factory implantada na chain selecionada. Elas não usam o verificador da Exchange nem seu domínio de endereço zero.
Domínio:
{
"name": "Hypercall Physical Covered Call",
"version": "1",
"chainId": "<selected chain id>",
"verifyingContract": "<exact PhysicalCoveredCallFactory address>"
}
Signatário: o market maker codificado em PhysicalCoveredCallQuote.marketMaker.
Tipos aninhados canônicos:
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)
A factory recalcula requestHash a partir do request aninhado completo antes de recuperar o signatário da cotação. Assim, a assinatura vincula o vendedor, o wrapper do ativo subjacente, a quantidade de cotas do wrapper, o strike, o vencimento, o prêmio, o prazo da cotação, o nonce, o chain id e o endereço da factory. O token de settlement e suas casas decimais são configuração autoritativa da factory, não valores assinados separadamente. Pyth está ausente desta geração sem oráculo. Tanto o digest da cotação quanto o nonce do maker são consumidos quando o vendedor financia um vault.
Somente o vendedor codificado no request pode enviar a cotação assinada. O funding emite o NFT de direito do lançador para o vendedor e o NFT da opção comprada para o market maker cotado, desde que esse maker seja um destinatário elegível enquanto a allowlist opcional de compradores estiver ativa. Uma assinatura válida autoriza o funding, não o exercício.
Somente o dono atual do NFT da opção comprada pode chamar o exercício. Essa regra de exclusividade do dono impede que um operador ERC-721 consuma a allowance do token de settlement do dono. Um operador aprovado ainda pode transferir o NFT pelas regras padrão do ERC-721, o que transfere o direito econômico para um destinatário elegível enquanto o filtro de compradores estiver ativo. Um exercício bem-sucedido puxa o caixa do strike do chamador-dono, entrega o ativo subjacente a esse dono e queima o NFT da opção comprada.
Separadores de Domínio EIP-712
Os três domínios de diretivas usam a mesma estrutura e diferem apenas em name. O verifyingContract é o endereço zero, então a mesma assinatura é válida para qualquer Account na chain, e é o endereço da Account dentro da mensagem que a vincula a uma única Account.
{
"name": "<DomainName>",
"version": "1",
"chainId": <chainId>,
"verifyingContract": "0x0000000000000000000000000000000000000000"
}
O tipo do domínio é EIP712Domain(string name,string version,uint256 chainId,address verifyingContract).
Chain IDs: mainnet 999, testnet 998. A Account seleciona o separador a partir da chain em que roda, então uma assinatura de testnet nunca é verificada na mainnet.
| Domínio | name | version | Signatário | Chain | Separador |
|---|---|---|---|---|---|
| API wallet | HypercallApiSign | 1 | API wallet | 999 | 0x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb |
| API wallet | HypercallApiSign | 1 | API wallet | 998 | 0x339bee4c00da9a5361f687797205c8d03f323659f5d9dc9e0505b9437ddee25e |
| Manager | HypercallManagerSign | 1 | Manager | 999 | 0xc9b5b0b8b0d9d7ba716326acbf795cfe431ef960a25a8f958d6569bea2f1516e |
| Manager | HypercallManagerSign | 1 | Manager | 998 | 0xd1f76b6138be892c14b71b0569bdb049cb44f239d34c78ef1ffaacd2466f9f18 |
| RSM | HypercallRsmSign | 1 | Signatário RSM | 999 | 0x3d0cae2af623c614099dbadd67a1e1457fabde576aa270a70a57e39bf338a7be |
| RSM | HypercallRsmSign | 1 | Signatário RSM | 998 | 0x650b282053fb61d3fd477bdc28f6434311fe905e27cc4ca643e87e802c45938c |
Calcule o separador você mesmo e compare antes de assinar qualquer coisa:
import { ethers } from "ethers";
const separator = ethers.TypedDataEncoder.hashDomain({
name: "HypercallApiSign",
version: "1",
chainId: 999,
verifyingContract: ethers.ZeroAddress
});
// 0x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb
Referência de Mensagens
Matriz de Signatários e Endpoints
| Mensagem | Domínio | Signatário | Enviar para | Executa |
|---|---|---|---|---|
HLOrder | API | API wallet | POST /v1/tee-perp/orders/submit, ou POST /v1/actions/hl_limit_order | Ordem limitada na Hyperliquid |
HLCancel | API | API wallet | POST /v1/tee-perp/cancels/submit-by-oid, ou POST /v1/actions/hl_cancel_by_oid | Cancelamento por oid |
HLCancelByCloid | API | API wallet | POST /v1/tee-perp/cancels/submit, ou POST /v1/actions/hl_cancel_by_cloid | Cancelamento por cloid |
HCPerpTriggerOrder | API | API wallet | POST /v1/tee-perp/orders/submit-trigger | Ordem trigger nativa (somente TEE) |
HCPerpOrderBatch | API | API wallet | POST /v1/tee-perp/orders/submit-batch | Lote de ordens nativo (somente TEE) |
HCPerpLeverageChange | API | API wallet | POST /v1/tee-perp/leverage/submit | Atualização de alavancagem (somente TEE) |
HCPerpScheduleCancel | API | API wallet | POST /v1/tee-perp/schedule-cancel/submit | Dead-man switch (somente TEE) |
HCUpdateApiWallet | Manager | Manager | POST /v1/actions/hc_update_api_wallet | Registro de API wallets da Account |
HLAddApiWallet | Manager | Manager | POST /v1/actions/hl_add_api_wallet | Aprovação de API wallet na HyperCore |
HLSendAsset | Manager | Manager | POST /v1/actions/hl_send_asset | sendAsset da HyperCore a partir da Account |
HLSetAbstraction | Manager | Manager | POST /v1/actions/hl_set_abstraction | Modo de conta na HyperCore (somente unificado) |
HCTransferOption | Manager | Manager | Não aceita | Reservada, rejeitada on-chain |
HLOrder, HLCancel, HLCancelByCloid, HLSendAsset | RSM | Signatário RSM | Somente sequencer | Ordens de recuperação e sweeps via Account |
System* | RSM | Signatário RSM | Somente sequencer | Créditos, saques e liquidação via Exchange |
Todas as rotas /v1/actions/{action} recebem account, nonce, action e signature. POST /v1/actions/{action}/typed-data retorna os dados tipados exatos a assinar para aquele request, que é a forma mais fácil de validar seu encoder. GET /v1/directives/{directive_id} informa o resultado on-chain. Os schemas de request estão na Referência da API.
Convenções de Transmissão
noncee todo campouint64,uint128ouuint256são inteiros JSON até9007199254740991, ou strings decimais. Use strings acima desse valor.signatureé uma string hex0xde 65 bytes (r || s || v).vpode ser0,1,27ou28.- Campos
bytes32são hex de 32 bytes com prefixo0x. Endereços são hex com checksum ou em minúsculas. - Preços e tamanhos de perpétuos são os inteiros
1e8da HyperCore, por exemplo$50,000é5000000000000e0.001moedas é100000.
Diretivas de API Wallet (HypercallApiSign)
Assinadas por uma API wallet ativa da Account. Use chain ID 999 e name HypercallApiSign.
Os vetores de teste usam uma conta placeholder e um nonce fixo para que você possa conferir seu encoder byte a byte. O digest é keccak256(0x1901 || domainSeparator || directiveStructHash).
HLOrder
Uma ordem limitada na Hyperliquid para a 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;
}
Tipo EIP-712 canônico:
HLOrder(address account,uint64 nonce,LimitOrder action)LimitOrder(uint32 asset,bool isBuy,uint64 limitPx,uint64 sz,bool reduceOnly,uint8 encodedTif,uint128 cloid)
Typehash: 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd. Signatário: API wallet. Ação: versão 1, id 1.
asset: o índice do ativo na Hyperliquid.GET /v1/tee-perp/marketslista os mercados de perpétuos que a Hypercall aceita e seus índices.isBuy:truepara comprar,falsepara vender.limitPx,sz: preço e tamanho multiplicados por1e8.reduceOnly:truese a ordem só puder reduzir uma posição.encodedTif: ALO =1, GTC =2, IOC =3. Qualquer outro valor é rejeitado.cloid: ID de ordem do cliente, diferente de zero. Você o usa depois para cancelar por cloid.
Exemplo (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);
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd |
| Hash da struct da ação | 0x0fd024c6bf8f132123e63a78d50008d8c39c52e5409ef6ca87a4eec8f6eabb41 |
| Hash da struct da diretiva | 0xd32948ee1f249b96124a6acdb5845d09aad8228512098598de6858d5484fe703 |
| Digest a assinar | 0xc3c42699092fe20c7dbc4205a1027f55c28d33a682a64bd3f04e40f1d28693f5 |
O vetor de teste usa isBuy: true, limitPx: 5000000000000, sz: 100000, reduceOnly: false, encodedTif: 2, asset: 0 e cloid igual ao nonce.
Envio: POST /v1/tee-perp/orders/submit com account, nonce, action e signature. A Hypercall executa a verificação de margem e, em seguida, um enclave seguro assina e envia a ordem nativa da Hyperliquid com o builder code da Hypercall anexado. O manager da Account precisa antes aprovar esse builder com Account.approveZeroFeeBuilder; consulte Onboarding. Veja Perpétuos para o fluxo completo.
{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 1760000000000,
"action": {
"asset": 0,
"isBuy": true,
"limitPx": "5000000000000",
"sz": "100000",
"reduceOnly": false,
"encodedTif": 2,
"cloid": "1760000000000"
},
"signature": "0x<65 byte signature>"
}
A mesma mensagem assinada também é aceita em POST /v1/actions/hl_limit_order, que a codifica como uma diretiva on-chain executada por meio de Exchange.executeUserDirective e Account.performCoreAction.
HLCancel
Cancela uma ordem pelo ID de ordem da Hyperliquid. O wrapper é HLCancel e a struct interna é 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. Signatário: API wallet. Ação: versão 1, id 10. Envio: POST /v1/tee-perp/cancels/submit-by-oid, ou 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);
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85 |
| Hash da struct da ação | 0xa34e7bb8af0d099f9c48095924e53067bcb9b542a816445b96abebbc5646b727 |
| Hash da struct da diretiva | 0x69d560ba5ef3e88459bde7fb8252e55dbc33627373c8f0cfcf8ef0868f59e097 |
| Digest a assinar | 0x5046aba9fb33c55ce736faf63734ea66914f3f168ff0aff2229fa6f31fa9b330 |
O vetor de teste usa asset: 0 e oid: 123456789.
HLCancelByCloid
Cancela uma ordem pelo ID de ordem do cliente que você definiu em 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. Signatário: API wallet. Ação: versão 1, id 11. Envio: POST /v1/tee-perp/cancels/submit, ou 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);
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5 |
| Hash da struct da ação | 0xfa4ab6440f946a6e279d90972d71223c768c01c8a91dc22703a6448dbcb966d0 |
| Hash da struct da diretiva | 0x998efb01bb9c842eea80e8cc084b9e4e7ec13b2111790e1acbfec32e49060d9d |
| Digest a assinar | 0x56af82a6aa7fa50907a23c6cfe3aa556af5aa087b1157163ebf6ea0240e8d29d |
O vetor de teste usa asset: 0 e cloid: 1760000000000.
Mensagens de Perpétuos Exclusivas do TEE
Estas quatro mensagens são verificadas pela API da Hypercall, não pelo contrato da Account, porque o enclave as executa nativamente na Hyperliquid e não existe diretiva on-chain para elas. Elas usam o mesmo domínio HypercallApiSign e a mesma autorização de API wallet que HLOrder (o signatário precisa ser uma API wallet ativa da Account, e a Account precisa estar em portfolio margin). Seus typehashes não estão nos contratos. Os nonces são tempo Unix em milissegundos.
PerpOrderTerms
HCPerpTriggerOrder e HCPerpOrderBatch incorporam esta struct. Uma ordem filha limitada assina seu byte de TIF com triggerPx = 0, isMarket = false, tpsl = 0. Uma ordem filha trigger assina encodedTif = 0, um triggerPx positivo e tpsl igual a 1 (take profit) ou 2 (stop loss).
struct PerpOrderTerms {
uint32 asset;
bool isBuy;
uint64 limitPx;
uint64 sz;
bool reduceOnly;
uint8 encodedTif;
uint64 triggerPx;
bool isMarket;
uint8 tpsl;
uint128 cloid;
}
HCPerpTriggerOrder
Uma ordem de stop loss ou take profit, enviada para POST /v1/tee-perp/orders/submit-trigger. O action.orderType do request precisa ser um trigger.
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
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x2d3104ab255275839aad254429e4be789f64a8d16b8e3e7d5f30a0db3c887b5c |
| Hash da struct da ação | 0x285b3186be219b92d7159419288c0dce9bc4ad7bfc9536e009ebf24bd67f434c |
| Hash da struct da diretiva | 0xaa03e40b34b15e7e932ae827921930e7538387b596ef1040dbcc791e69021299 |
| Digest a assinar | 0xc46aadc390b66c235af15e199e188ab23fb7f7f1b9237f6c2849c264c28d94da |
O vetor de teste é uma venda stop loss a mercado reduce-only: asset: 0, isBuy: false, limitPx: 4800000000000 (pior preço), sz: 100000, reduceOnly: true, encodedTif: 0, triggerPx: 4900000000000, isMarket: true, tpsl: 2, cloid: 1760000000001.
HCPerpOrderBatch
Até 100 ordens sob um único agrupamento, enviadas para POST /v1/tee-perp/orders/submit-batch. Cada ordem precisa usar um cloid distinto. grouping é 0 (sem agrupamento), 1 (normalTpsl) ou 2 (positionTpsl). Um lote conta como uma única colocação de ordem no rate limit.
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. O array orders é codificado como keccak256 dos hashes das structs PerpOrderTerms concatenados, na ordem de envio.
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x9d4f467a44f4b0d39f234f3b91888546ce31dcbb67ce791550901b9042c38f8b |
| Hash do array de ordens | 0x13fc75fcc69bf3b4ef7cdc3a0872c3cc1cf59440c74d366055109b6bd5ea7c98 |
| Hash da struct da diretiva | 0x69d0b1131e386769823fe1ab3facbe8e6fc013f86a117cf95cb52b8ce2f274e0 |
| Digest a assinar | 0x4b5cd34b1f254fdd9881b7674a3412807e16cade1f2ccc7a1e261482682fbd07 |
O vetor de teste é grouping: 1 com duas ordens: uma compra limitada GTC (limitPx: 5000000000000, sz: 100000, cloid: 1760000000000) seguida do stop loss do exemplo de trigger.
HCPerpLeverageChange
Define a alavancagem de um ativo, enviada para POST /v1/tee-perp/leverage/submit. leverage precisa ser maior que zero.
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
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0xe13845f0e6c16a5e1fc56b2d11fb0972faa2ec30b01e94d58c72147fa9b6a463 |
| Hash da struct da ação | 0x0e6e271dd56192d7fb1f37ea2eaffecfbbe2d1f79cac78dce6a6930bb8cc253e |
| Hash da struct da diretiva | 0xe04b169bbb0e20042308e5aad1036ce60eda75f484a4d6093dc60f2c2231129e |
| Digest a assinar | 0xb2a43487152a7cecc73d2b6b84d817a58dd02c559b05289a8d8e1b5c3d25e266 |
O vetor de teste define alavancagem cross de 5x em asset: 0.
HCPerpScheduleCancel
O dead-man switch da Hyperliquid: cancela todas as ordens abertas em time (milissegundos Unix, com pelo menos sete segundos de antecedência). Enviada para POST /v1/tee-perp/schedule-cancel/submit. Para remover um cancelamento agendado, omita time no request e assine time = 0. Enviar um 0 explícito é rejeitado.
struct PerpScheduleCancel {
uint64 time;
}
struct HCPerpScheduleCancel {
address account;
uint64 nonce;
PerpScheduleCancel action;
}
HCPerpScheduleCancel(address account,uint64 nonce,PerpScheduleCancel action)PerpScheduleCancel(uint64 time)
Typehash: 0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb |
| Hash da struct da ação | 0x0a3ebfe48ef28a79beeee4d56e524f8a5280c38562efb697e7b1d63b3d475afc |
| Hash da struct da diretiva | 0xae64a13943a6a35b33aeb3095763b855c58c2119daf71e1e3228d8acf2645e8b |
| Digest a assinar | 0xa01806f47299010b5963a516562be3c3b44fed4f4a9e2e56c4bb601630146cdc |
O vetor de teste agenda um cancelamento em time: 1760000060000.
Cancelamento Preparado Assinado pelo Manager
POST /v1/tee-perp/cancels/submit-prepared é o caminho de cancelamento assinado pelo manager. Ele não usa uma struct de dados tipados. O manager assina o digest de um cancelamento nativo da Hyperliquid já preparado, fornecido como preparedRequest (base64) com managerSignature na forma canônica low-s, além de uma authenticationSignature com timestamp que autentica a carteira do manager. Consulte a Referência da API para o schema do request.
Diretivas do Manager (HypercallManagerSign)
Assinadas pelo manager da Account. Use chain ID 999 e name HypercallManagerSign. A Account exige signer == manager. Envie com POST /v1/actions/{action}.
HCUpdateApiWallet
Adiciona, substitui ou remove (addr = 0x0) a API wallet armazenada sob name na 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. Ação: versão 0, id 2. Envio: POST /v1/actions/hc_update_api_wallet com action igual a { "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);
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x8ebe7d19374200e5dc3ae838db74b370da95bd2b3a8aec9de85d2398dd4a9257 |
| Hash da struct da ação | 0x8b6c4a9db102e9d27c9a4069b39ba35e04948129359f0c15cd5103dd101ffce7 |
| Hash da struct da diretiva | 0x830e291835ad182f290bc3d2bff09eaf9fd33acfbe44c6ad583218cd1a8232e5 |
| Digest a assinar | 0x06589077544af449314db1fa8c7aac2d277cce9e833a04992d88161ede24cbe8 |
O vetor de teste usa name trading-bot (0x74726164696e672d626f74 preenchido com zeros à direita) e addr 0x2222222222222222222222222222222222222222. Consulte Onboarding para o fluxo completo de API wallet. A Account emite ApiWalletUpdated(name, addr).
HLAddApiWallet
Aprova uma API wallet da Hyperliquid para a Account na 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. Ação: versão 1, id 9. Envio: POST /v1/actions/hl_add_api_wallet.
apiWalletName é uma string, então seu campo na struct é keccak256(bytes(apiWalletName)). Ethers e viem fazem isso por você.
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x71c0e0dfbddc3456015249946354324befde42b6851d1c9b26c6a29f2e0b1ac2 |
| Hash da struct da ação | 0xed32a441b0ee59c0252f5dff3411766289c9c35c19e3152b0b2b204176c2c7cd |
| Hash da struct da diretiva | 0xb990a3dfb4e8d96243539f8758b3a55249b217542bb4112f4f88ed67ec516ed9 |
| Digest a assinar | 0x584886d020316085de0e0dec16331b8e990558be3e8fd004c47200abbebed518 |
O vetor de teste usa apiWalletAddress 0x2222222222222222222222222222222222222222 e apiWalletName hl-bot.
HLSendAsset
Envia ativos da Account na HyperCore para um destino.
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. Ação: versão 1, id 13. Envio: 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);
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595 |
| Hash da struct da ação | 0x9b8c0290da19ea1069e14833023c4621a4f043354b36b4f17d4803b1fce6e656 |
| Hash da struct da diretiva | 0xa0cb8a72188a61289fc2685c29a424605e0a2ee7b7af3e8cfee10e1c75153e08 |
| Digest a assinar | 0x7c7037f27c659a1885f744778480e6847c5d08e98fb22517265ba708b6597d10 |
O vetor de teste envia 5 USDC (amountWei: 500000000) de perpétuos (srcDex: 0) para spot (dstDex: 4294967295) com destination igual à Exchange de produção 0xE6b7FaA216cabb2b38B392f577C9c826378b2240.
HLSetAbstraction
Define o modo de conta da Account na HyperCore. A Account só aceita user igual a ela mesma e abstraction = 2 (conta unificada); qualquer outro valor reverte. Portfolio Margin exige essa configuração.
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. Ação: versão 1, id 16. Envio: POST /v1/actions/hl_set_abstraction.
Vetor de teste (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0xcf5fddf081e5f2a9a45aa87cb1a3c42e5aa20164566b1ad2369b6b1318eac786 |
| Hash da struct da ação | 0xef6c70a3c14b9e77c710c6b3b3ee681ca270ef884bd8a64fa4064a96f3dda84e |
| Hash da struct da diretiva | 0xdda9d0fe82b63c728c4ac42585d5998a04cabaed0f957a2cafdf31a754829c3d |
| Digest a assinar | 0xf49d7d8d74596e503d6a1bdfb26653533a12a5ba3816acd992d0bd4ef378f59d |
O vetor de teste define user como a Account e abstraction como 2.
HCTransferOption (reservada)
Os contratos definem HCTransferOption(address account,uint64 nonce,TransferOption action)TransferOption(address recipient,address option,uint256 amountWei) (typehash 0xa218e1158788b23987f954edc7a07659a03a03fe5ba981a5bbe44d7a146e0819, ação versão 0, id 1), mas nenhum tipo de signatário está atribuído a ela. A Account reverte com Account__UserDirectiveNotSupported, e a API rejeita hc_transfer_option. Não a assine. Movimente tokens de opção com depositOption e saques.
Transações do Manager sem Assinatura
Algumas ações do manager são chamadas diretas à Account, não mensagens EIP-712: Account.approveZeroFeeBuilder(builder) aprova um builder da Hyperliquid com taxa máxima de 0% e é obrigatória uma vez antes da primeira ordem de perpétuo (consulte Onboarding). Account.transferTo(recipient, token, amount) move tokens para fora da Account na HyperEVM. Ambas exigem msg.sender == manager e revertem enquanto a Account estiver em liquidação.
Diretivas RSM (HypercallRsmSign)
Assinadas pelo signatário RSM e enviadas pelo sequencer. Elas creditam depósitos, processam saques, iniciam e encerram liquidações e colocam ordens de recuperação IOC reduce-only. Market makers e usuários não as assinam nem as enviam; elas estão documentadas para que você possa verificar o que o protocolo pode fazer com uma Account. Use chain ID 999 e name HypercallRsmSign. A Exchange verifica signer == rsmSigner (atualmente 0x502E7fAbF34E84EeB115C34FE947b79A94dF886E na mainnet) e o chamador precisa ter SEQUENCER_ROLE.
Ordens e Sweeps RSM (executados pela Account)
Estas reutilizam as structs HL sob o domínio RSM, então os typehashes são iguais aos de API e manager e só o separador de domínio muda. A Account impõe restrições adicionais e as executa mesmo durante a liquidação.
| Mensagem | Typehash | Restrição imposta pela Account |
|---|---|---|
HLOrder | 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd | encodedTif precisa ser IOC (3), e a ordem precisa ser reduceOnly, ou uma venda spot para USDC (ids de ativo spot de 10000 a 99999) limitada a no máximo 5% abaixo do preço spot da HyperCore |
HLCancel | 0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85 | Nenhuma |
HLCancelByCloid | 0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5 | Nenhuma |
HLSendAsset | 0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595 | destination precisa ser a Exchange |
Vetor de teste RSM HLOrder (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd |
| Hash da struct da ação | 0x39b4e0699f382aaad23f04740034e7c5581ba918139d2db63fbf586cc447e7db |
| Hash da struct da diretiva | 0xe6dde5ad6d310b5ebb83c09ec28ee5568700473b885bb483b7437dca202af4f3 |
| Digest a assinar | 0x57afa1e810804e768c05a467aa88ede15fdceedae5aaa840adff61a613aca469 |
O vetor RSM HLOrder é uma venda IOC reduce-only (isBuy: false, limitPx: 4800000000000, sz: 100000, reduceOnly: true, encodedTif: 3, cloid igual ao nonce). Exchange.executeRsmDirective verifica a assinatura e encaminha a ação para a Account.
Ações de Sistema (executadas pela Exchange)
Versão 255. Cada wrapper é System<Action>(address account,uint64 nonce,<Action> action)<Action>(...).
| Wrapper | Tipo interno | 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 |
Strings de tipo externas completas:
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 credita tokens spot ou de perpétuos da HyperCore para a Account.
amountWeiprecisa ser diferente de zero e a Account precisa estar ativada na HyperCore. - SystemCreditOption emite tokens de opção para a Account, implantando o par de opções se necessário.
underlyingé uma palavraShortStringda OpenZeppelin: ASCII alinhado à esquerda com o comprimento em bytes no último byte (BTCé0x42544300...03). Codificações não canônicas revertem. - SystemStartLiquidation registra os parâmetros do leilão e bloqueia a Account.
marginNeededprecisa ser diferente de zero. - SystemStopLiquidation exige que
startTimeseja igual ao início registrado e devolve a Account ao seu manager. - SystemWithdrawToken enfileira a entrega de Standard USDC na HyperCore a partir do saldo próprio da Exchange. Exige
subAccount = 0,srcDex = 0,dstDexigual a0ou4294967295,token = 0(USDC) e umamountWeique seja múltiplo inteiro da unidade EVM. Um recibo na HyperEVM sozinho não é prova de entrega na HyperCore.
Vetor de teste SystemCreditToken (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052 |
| Hash da struct da ação | 0xc69d7c6e5c36c9789d990c6316eaff3be43980583806f41f8a8e6461b7114011 |
| Hash da struct da diretiva | 0x7ffa37cef7e08d3a2dd5501a8648899d37bc09ebb25d148c124e12c5047476e1 |
| Digest a assinar | 0x95f75e5ddb4837de3f578b8aa0d714d4b02672b18c4929e3d2dda4a266de8254 |
O vetor credita 5 USDC (srcDex e dstDex iguais a 4294967295, token: 0, amountWei: 500000000).
Vetor de teste SystemCreditOption (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae |
| Hash da struct da ação | 0x4a8b563fc94d26c1da376145d5aa5d05f996232fcf9739ed0a662650e91861b6 |
| Hash da struct da diretiva | 0x190b638f1a462469bf0d070248acfc86bbbb95ea8a9d3d97d33581c7d6bb5554 |
| Digest a assinar | 0x86fb7c53bb7e139a4d5df7db2feae40e634efe09ea7509165d3cece75d75fce2 |
O vetor credita uma call de BTC (underlying: 0x42544300...03, expiry: 1761811200, strike: 80000, isCall: true, amountWei: 1000000000000000000).
Vetor de teste SystemStartLiquidation (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e |
| Hash da struct da ação | 0x4cd6a7f0997eba84ef82eabd429a0d9ca80e55bd6d89d2e67eda9970d87ec803 |
| Hash da struct da diretiva | 0x84f18dc2577978d7890c9eb269fd787d99de37039b3a08e24745398feffbd0c5 |
| Digest a assinar | 0xcc72c0e7829938c9ca0a4515d759f94cc96d2f24cd51a134a430f215ed5f5d4b |
O vetor usa equity: -1500000000 e marginNeeded: 20000000000 (ambos em USDC com seis casas decimais).
Vetor de teste SystemStopLiquidation (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3 |
| Hash da struct da ação | 0x1d900a795b328bd5fa734bd6d7f74634b98ca66eb5e45322fb1ba6400564b62b |
| Hash da struct da diretiva | 0x977b9becdd26830f2cdf70ab40f72f24490fe6ed45822d1fc8c84120e9a46f40 |
| Digest a assinar | 0xbe65f82782b14dba42e334e32dd7dcc6bf14c96824523723a186a7381f8f12af |
O vetor usa startTime: 1760000000.
Vetor de teste SystemWithdrawToken (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):
| Etapa | Valor |
|---|---|
| Typehash | 0x634b866e9a922bb846e297973c7a456e641b88f4e97493da9b222084d799c883 |
| Hash da struct da ação | 0x10bd8d4372a09e613a6b4fb7018fcccde857ebf6cc3327d6c9a3c0f81515a076 |
| Hash da struct da diretiva | 0x86680427965513c65a7a170730b9f4fb2e2b40e22cd18338cb004b6a7872ada2 |
| Digest a assinar | 0x65cc392038decb9ccdc23b0a4a1cfbe657d3417f8cd9ebf2319b3172fb7d885c |
O vetor saca 5 USDC (amountWei: 500000000) para destination 0x1111111111111111111111111111111111111111 com srcDex: 0, dstDex: 0, token: 0.
Nonces
Cada signatário tem um espaço de nonces independente, controlado em três lugares.
- Contrato da Account: um bitmap por signatário.
Account.isNonceUsed(signer, nonce)retorna se um nonce já foi consumido. Uma diretiva de usuário reverte comAccount__NonceAlreadyUsedem caso de reuso. Não existenextNonce; lacunas são permitidas e a ordem não importa on-chain. - Contrato da Exchange: um bitmap para o signatário RSM, lido com
Exchange.isNonceUsed(signer, nonce). - Engine: guarda os 100 maiores nonces por signatário. Um novo nonce não pode estar no conjunto, precisa ser maior que o menor nonce armazenado quando o conjunto estiver cheio e precisa estar estritamente dentro de dois dias antes e um dia depois do horário do servidor em milissegundos.
Use o tempo Unix atual em milissegundos como semente do nonce e incremente por signatário. Dois requests assinados pela mesma carteira no mesmo milissegundo precisam de nonces distintos, então mantenha um contador. Nas rotas de perpétuos via TEE, o nonce também é a âncora de tempo do request, então use timestamps reais em milissegundos ali, e não inteiros pequenos.
function isNonceUsed(address signer, uint256 nonce) external view returns (bool);
Fluxo de Verificação de Assinatura
- Off-chain: o signatário monta o digest EIP-712 (
0x1901 || domainSeparator || structHash) e o assina. - API: a Hypercall recupera o signatário, verifica se é uma API wallet ativa ou o manager, executa a verificação de margem da engine para ordens e então enfileira a diretiva. A resposta informa o estágio real, os detalhes de rejeição e o hash da transação.
- Sequencer: envia
Exchange.executeUserDirective(directive, signature). A Exchange verifica se a Account existe e encaminha paraAccount.executeUserDirective. - Account: reconstrói o digest a partir do próprio endereço, do nonce e da ação, recupera o signatário com o separador de API ou de manager correspondente àquela ação, verifica a autorização, consome o nonce e então executa. Ações HL vão para o CoreWriter da HyperCore. Ações HC atualizam o registro de API wallets.
- Cliente: consulta
GET /v1/directives/{directive_id}para obter o status final.
As rotas de perpétuos via TEE param após a etapa da API: é o enclave, e não a Account, que executa a ordem na 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
Descontinuados e Removidos
Estes itens apareciam em versões anteriores desta página e não fazem mais parte do sistema implantado. Eles estão listados para que integrações construídas sobre eles possam ser migradas.
- Codificação Processor e ActionCaster. O contrato
Processore a codificação de mensagens ActionCaster foram removidos na Exchange0.2.0(fevereiro de 2026). As diretivas de Account agora passam porExchange.executeUserDirectivee pelo CoreWriter. A Exchange0.6.1implantada não tem nenhum dos antigos pontos de entrada. - Pontos de entrada da Exchange com structs próprias.
hlRequestOrder,hlRequestCancel,hlRequestCancelByCloid,hlActionSendAsset,hcActionWithdrawToken,hcActionWithdrawOption,rsmCommandRebalanceersmCommandRepaynão existem mais. Seus substitutos:
| Mensagem removida | Substituto |
|---|---|
HLRequestCancel (lote de HLCancel{asset,oid} mais nonce) | HLCancel com um CancelOrderByOid por diretiva |
HLRequestCancelByCloid | HLCancelByCloid com um CancelOrderByCloid por diretiva |
HLActionSendAsset (account, nonce, destination, srcDex, dstDex, token, amountWei) | HLSendAsset com SendAsset, que adiciona subAccount |
HCActionWithdrawToken | SystemWithdrawToken assinada pelo RSM, executada pelo sequencer após a engine aprovar o saque |
HCActionWithdrawOption | Créditos de opções são SystemCreditOption do RSM; depósitos usam depositOption |
RsmCommandRebalance | HLOrder assinada pelo RSM (IOC reduce-only) |
RsmCommandRepay | HLSendAsset assinada pelo RSM para a Exchange |
- Funções de ordem legadas.
placeCoreOrders,cancelCoreOrdersecancelCoreOrdersByCloidusavam codificação MsgPack e o domínioCoreSignatures("Exchange", chain ID1337). Foram removidas. nextNonce. O contador on-chainnextNonce[signer]não existe mais. Resta apenas o bitmap de nonces usados (isNonceUsed).- Separadores de mainnet marcados como TBD. O texto anterior listava os separadores de mainnet do manager e do RSM como TBD. Os três estão definidos e listados acima.
HCTransferOption. Definida, mas nunca habilitada; veja acima.
Considerações de Segurança
- Chaves: mantenha a chave do manager em uma carteira de hardware. API wallets só assinam ordens e cancelamentos; use chaves separadas por sistema.
- Replay de nonce: nunca reutilize um nonce. Controle os nonces off-chain e incremente de forma atômica.
- Domínio: sempre assine com chain ID
999na mainnet (998na testnet) e confira o separador que você calculou com a tabela acima. - Verifique o que você assina: chame
POST /v1/actions/{action}/typed-datae compare com seu próprio encoder antes de assinar com uma carteira de hardware. - A verificação on-chain é definitiva: a API pré-verifica as assinaturas, mas a Account verifica novamente cada diretiva on-chain. Não trate uma confirmação da API como execução.
- Manager vs API wallet: managers controlam a titularidade, as API wallets e a movimentação de ativos. API wallets só assinam mensagens de negociação. Use chaves separadas.
Referências
- Onboarding para criação de Account e configuração de API wallet
- Visão geral dos contratos para endereços implantados e tipos de diretiva
- Perpétuos para o fluxo de ordens de perpétuos
- Autenticação e Assinatura para assinatura de ordens de opções