Esta página foi traduzida automaticamente. O original em inglês é a versão canônica. Ler em inglês →
Pular para o conteúdo principal

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:

  1. API wallet: um endereço registrado na Account com hc_update_api_wallet (Account.isApiWalletActive). Assina ordens e cancelamentos.
  2. Manager: o dono da Account (Account.manager). Assina alterações de API wallet, envios de ativos e mudanças de modo de conta.
  3. 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):

BytesCampoSignificado
20accountO endereço da Account (address)
8nonceO nonce do signatário (uint64)
1versionFamília da ação
3idID da ação dentro da família
restantedataabi.encode da struct interna da ação
VersãoFamíliaIDs de ação
0HyperCall (HC)2 atualizar API wallet. 1 (transferir opção) é reservado e rejeitado.
1HyperLiquid (HL)1 ordem limitada, 9 adicionar API wallet, 10 cancelar por oid, 11 cancelar por cloid, 13 enviar ativo, 16 definir abstraction
255System1 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ínionameversionSignatárioChainSeparador
API walletHypercallApiSign1API wallet9990x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb
API walletHypercallApiSign1API wallet9980x339bee4c00da9a5361f687797205c8d03f323659f5d9dc9e0505b9437ddee25e
ManagerHypercallManagerSign1Manager9990xc9b5b0b8b0d9d7ba716326acbf795cfe431ef960a25a8f958d6569bea2f1516e
ManagerHypercallManagerSign1Manager9980xd1f76b6138be892c14b71b0569bdb049cb44f239d34c78ef1ffaacd2466f9f18
RSMHypercallRsmSign1Signatário RSM9990x3d0cae2af623c614099dbadd67a1e1457fabde576aa270a70a57e39bf338a7be
RSMHypercallRsmSign1Signatário RSM9980x650b282053fb61d3fd477bdc28f6434311fe905e27cc4ca643e87e802c45938c

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​

MensagemDomínioSignatárioEnviar paraExecuta
HLOrderAPIAPI walletPOST /v1/tee-perp/orders/submit, ou POST /v1/actions/hl_limit_orderOrdem limitada na Hyperliquid
HLCancelAPIAPI walletPOST /v1/tee-perp/cancels/submit-by-oid, ou POST /v1/actions/hl_cancel_by_oidCancelamento por oid
HLCancelByCloidAPIAPI walletPOST /v1/tee-perp/cancels/submit, ou POST /v1/actions/hl_cancel_by_cloidCancelamento por cloid
HCPerpTriggerOrderAPIAPI walletPOST /v1/tee-perp/orders/submit-triggerOrdem trigger nativa (somente TEE)
HCPerpOrderBatchAPIAPI walletPOST /v1/tee-perp/orders/submit-batchLote de ordens nativo (somente TEE)
HCPerpLeverageChangeAPIAPI walletPOST /v1/tee-perp/leverage/submitAtualização de alavancagem (somente TEE)
HCPerpScheduleCancelAPIAPI walletPOST /v1/tee-perp/schedule-cancel/submitDead-man switch (somente TEE)
HCUpdateApiWalletManagerManagerPOST /v1/actions/hc_update_api_walletRegistro de API wallets da Account
HLAddApiWalletManagerManagerPOST /v1/actions/hl_add_api_walletAprovação de API wallet na HyperCore
HLSendAssetManagerManagerPOST /v1/actions/hl_send_assetsendAsset da HyperCore a partir da Account
HLSetAbstractionManagerManagerPOST /v1/actions/hl_set_abstractionModo de conta na HyperCore (somente unificado)
HCTransferOptionManagerManagerNão aceitaReservada, rejeitada on-chain
HLOrder, HLCancel, HLCancelByCloid, HLSendAssetRSMSignatário RSMSomente sequencerOrdens de recuperação e sweeps via Account
System*RSMSignatário RSMSomente sequencerCré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​

  • nonce e todo campo uint64, uint128 ou uint256 são inteiros JSON até 9007199254740991, ou strings decimais. Use strings acima desse valor.
  • signature é uma string hex 0x de 65 bytes (r || s || v). v pode ser 0, 1, 27 ou 28.
  • Campos bytes32 são hex de 32 bytes com prefixo 0x. Endereços são hex com checksum ou em minúsculas.
  • Preços e tamanhos de perpétuos são os inteiros 1e8 da HyperCore, por exemplo $50,000 é 5000000000000 e 0.001 moedas é 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/markets lista os mercados de perpétuos que a Hypercall aceita e seus índices.
  • isBuy: true para comprar, false para vender.
  • limitPx, sz: preço e tamanho multiplicados por 1e8.
  • reduceOnly: true se 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):

EtapaValor
Typehash0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd
Hash da struct da ação0x0fd024c6bf8f132123e63a78d50008d8c39c52e5409ef6ca87a4eec8f6eabb41
Hash da struct da diretiva0xd32948ee1f249b96124a6acdb5845d09aad8228512098598de6858d5484fe703
Digest a assinar0xc3c42699092fe20c7dbc4205a1027f55c28d33a682a64bd3f04e40f1d28693f5

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):

EtapaValor
Typehash0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85
Hash da struct da ação0xa34e7bb8af0d099f9c48095924e53067bcb9b542a816445b96abebbc5646b727
Hash da struct da diretiva0x69d560ba5ef3e88459bde7fb8252e55dbc33627373c8f0cfcf8ef0868f59e097
Digest a assinar0x5046aba9fb33c55ce736faf63734ea66914f3f168ff0aff2229fa6f31fa9b330

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):

EtapaValor
Typehash0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5
Hash da struct da ação0xfa4ab6440f946a6e279d90972d71223c768c01c8a91dc22703a6448dbcb966d0
Hash da struct da diretiva0x998efb01bb9c842eea80e8cc084b9e4e7ec13b2111790e1acbfec32e49060d9d
Digest a assinar0x56af82a6aa7fa50907a23c6cfe3aa556af5aa087b1157163ebf6ea0240e8d29d

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):

EtapaValor
Typehash0x2d3104ab255275839aad254429e4be789f64a8d16b8e3e7d5f30a0db3c887b5c
Hash da struct da ação0x285b3186be219b92d7159419288c0dce9bc4ad7bfc9536e009ebf24bd67f434c
Hash da struct da diretiva0xaa03e40b34b15e7e932ae827921930e7538387b596ef1040dbcc791e69021299
Digest a assinar0xc46aadc390b66c235af15e199e188ab23fb7f7f1b9237f6c2849c264c28d94da

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):

EtapaValor
Typehash0x9d4f467a44f4b0d39f234f3b91888546ce31dcbb67ce791550901b9042c38f8b
Hash do array de ordens0x13fc75fcc69bf3b4ef7cdc3a0872c3cc1cf59440c74d366055109b6bd5ea7c98
Hash da struct da diretiva0x69d0b1131e386769823fe1ab3facbe8e6fc013f86a117cf95cb52b8ce2f274e0
Digest a assinar0x4b5cd34b1f254fdd9881b7674a3412807e16cade1f2ccc7a1e261482682fbd07

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):

EtapaValor
Typehash0xe13845f0e6c16a5e1fc56b2d11fb0972faa2ec30b01e94d58c72147fa9b6a463
Hash da struct da ação0x0e6e271dd56192d7fb1f37ea2eaffecfbbe2d1f79cac78dce6a6930bb8cc253e
Hash da struct da diretiva0xe04b169bbb0e20042308e5aad1036ce60eda75f484a4d6093dc60f2c2231129e
Digest a assinar0xb2a43487152a7cecc73d2b6b84d817a58dd02c559b05289a8d8e1b5c3d25e266

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):

EtapaValor
Typehash0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb
Hash da struct da ação0x0a3ebfe48ef28a79beeee4d56e524f8a5280c38562efb697e7b1d63b3d475afc
Hash da struct da diretiva0xae64a13943a6a35b33aeb3095763b855c58c2119daf71e1e3228d8acf2645e8b
Digest a assinar0xa01806f47299010b5963a516562be3c3b44fed4f4a9e2e56c4bb601630146cdc

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):

EtapaValor
Typehash0x8ebe7d19374200e5dc3ae838db74b370da95bd2b3a8aec9de85d2398dd4a9257
Hash da struct da ação0x8b6c4a9db102e9d27c9a4069b39ba35e04948129359f0c15cd5103dd101ffce7
Hash da struct da diretiva0x830e291835ad182f290bc3d2bff09eaf9fd33acfbe44c6ad583218cd1a8232e5
Digest a assinar0x06589077544af449314db1fa8c7aac2d277cce9e833a04992d88161ede24cbe8

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):

EtapaValor
Typehash0x71c0e0dfbddc3456015249946354324befde42b6851d1c9b26c6a29f2e0b1ac2
Hash da struct da ação0xed32a441b0ee59c0252f5dff3411766289c9c35c19e3152b0b2b204176c2c7cd
Hash da struct da diretiva0xb990a3dfb4e8d96243539f8758b3a55249b217542bb4112f4f88ed67ec516ed9
Digest a assinar0x584886d020316085de0e0dec16331b8e990558be3e8fd004c47200abbebed518

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):

EtapaValor
Typehash0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595
Hash da struct da ação0x9b8c0290da19ea1069e14833023c4621a4f043354b36b4f17d4803b1fce6e656
Hash da struct da diretiva0xa0cb8a72188a61289fc2685c29a424605e0a2ee7b7af3e8cfee10e1c75153e08
Digest a assinar0x7c7037f27c659a1885f744778480e6847c5d08e98fb22517265ba708b6597d10

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):

EtapaValor
Typehash0xcf5fddf081e5f2a9a45aa87cb1a3c42e5aa20164566b1ad2369b6b1318eac786
Hash da struct da ação0xef6c70a3c14b9e77c710c6b3b3ee681ca270ef884bd8a64fa4064a96f3dda84e
Hash da struct da diretiva0xdda9d0fe82b63c728c4ac42585d5998a04cabaed0f957a2cafdf31a754829c3d
Digest a assinar0xf49d7d8d74596e503d6a1bdfb26653533a12a5ba3816acd992d0bd4ef378f59d

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.

MensagemTypehashRestrição imposta pela Account
HLOrder0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707ddencodedTif 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
HLCancel0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85Nenhuma
HLCancelByCloid0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5Nenhuma
HLSendAsset0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595destination precisa ser a Exchange

Vetor de teste RSM HLOrder (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):

EtapaValor
Typehash0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd
Hash da struct da ação0x39b4e0699f382aaad23f04740034e7c5581ba918139d2db63fbf586cc447e7db
Hash da struct da diretiva0xe6dde5ad6d310b5ebb83c09ec28ee5568700473b885bb483b7437dca202af4f3
Digest a assinar0x57afa1e810804e768c05a467aa88ede15fdceedae5aaa840adff61a613aca469

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>(...).

WrapperTipo internoTypehash
SystemCreditTokenCreditToken(uint32 srcDex,uint32 dstDex,uint64 token,uint64 amountWei)0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052
SystemCreditOptionCreditOption(bytes32 underlying,uint256 expiry,uint256 strike,bool isCall,uint256 amountWei)0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae
SystemStartLiquidationStartLiquidation(int256 equity,uint256 marginNeeded)0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e
SystemStopLiquidationStopLiquidation(uint256 startTime)0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3
SystemWithdrawTokenWithdrawToken(address destination,address subAccount,uint32 srcDex,uint32 dstDex,uint64 token,uint64 amountWei)0x634b866e9a922bb846e297973c7a456e641b88f4e97493da9b222084d799c883

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. amountWei precisa 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 palavra ShortString da 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. marginNeeded precisa ser diferente de zero.
  • SystemStopLiquidation exige que startTime seja 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, dstDex igual a 0 ou 4294967295, token = 0 (USDC) e um amountWei que 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):

EtapaValor
Typehash0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052
Hash da struct da ação0xc69d7c6e5c36c9789d990c6316eaff3be43980583806f41f8a8e6461b7114011
Hash da struct da diretiva0x7ffa37cef7e08d3a2dd5501a8648899d37bc09ebb25d148c124e12c5047476e1
Digest a assinar0x95f75e5ddb4837de3f578b8aa0d714d4b02672b18c4929e3d2dda4a266de8254

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):

EtapaValor
Typehash0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae
Hash da struct da ação0x4a8b563fc94d26c1da376145d5aa5d05f996232fcf9739ed0a662650e91861b6
Hash da struct da diretiva0x190b638f1a462469bf0d070248acfc86bbbb95ea8a9d3d97d33581c7d6bb5554
Digest a assinar0x86fb7c53bb7e139a4d5df7db2feae40e634efe09ea7509165d3cece75d75fce2

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):

EtapaValor
Typehash0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e
Hash da struct da ação0x4cd6a7f0997eba84ef82eabd429a0d9ca80e55bd6d89d2e67eda9970d87ec803
Hash da struct da diretiva0x84f18dc2577978d7890c9eb269fd787d99de37039b3a08e24745398feffbd0c5
Digest a assinar0xcc72c0e7829938c9ca0a4515d759f94cc96d2f24cd51a134a430f215ed5f5d4b

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):

EtapaValor
Typehash0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3
Hash da struct da ação0x1d900a795b328bd5fa734bd6d7f74634b98ca66eb5e45322fb1ba6400564b62b
Hash da struct da diretiva0x977b9becdd26830f2cdf70ab40f72f24490fe6ed45822d1fc8c84120e9a46f40
Digest a assinar0xbe65f82782b14dba42e334e32dd7dcc6bf14c96824523723a186a7381f8f12af

O vetor usa startTime: 1760000000.

Vetor de teste SystemWithdrawToken (account 0x1111111111111111111111111111111111111111, nonce 1760000000000, chain 999):

EtapaValor
Typehash0x634b866e9a922bb846e297973c7a456e641b88f4e97493da9b222084d799c883
Hash da struct da ação0x10bd8d4372a09e613a6b4fb7018fcccde857ebf6cc3327d6c9a3c0f81515a076
Hash da struct da diretiva0x86680427965513c65a7a170730b9f4fb2e2b40e22cd18338cb004b6a7872ada2
Digest a assinar0x65cc392038decb9ccdc23b0a4a1cfbe657d3417f8cd9ebf2319b3172fb7d885c

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 com Account__NonceAlreadyUsed em caso de reuso. Não existe nextNonce; 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​

  1. Off-chain: o signatário monta o digest EIP-712 (0x1901 || domainSeparator || structHash) e o assina.
  2. 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.
  3. Sequencer: envia Exchange.executeUserDirective(directive, signature). A Exchange verifica se a Account existe e encaminha para Account.executeUserDirective.
  4. 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.
  5. 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 Processor e a codificação de mensagens ActionCaster foram removidos na Exchange 0.2.0 (fevereiro de 2026). As diretivas de Account agora passam por Exchange.executeUserDirective e pelo CoreWriter. A Exchange 0.6.1 implantada não tem nenhum dos antigos pontos de entrada.
  • Pontos de entrada da Exchange com structs próprias. hlRequestOrder, hlRequestCancel, hlRequestCancelByCloid, hlActionSendAsset, hcActionWithdrawToken, hcActionWithdrawOption, rsmCommandRebalance e rsmCommandRepay não existem mais. Seus substitutos:
Mensagem removidaSubstituto
HLRequestCancel (lote de HLCancel{asset,oid} mais nonce)HLCancel com um CancelOrderByOid por diretiva
HLRequestCancelByCloidHLCancelByCloid com um CancelOrderByCloid por diretiva
HLActionSendAsset (account, nonce, destination, srcDex, dstDex, token, amountWei)HLSendAsset com SendAsset, que adiciona subAccount
HCActionWithdrawTokenSystemWithdrawToken assinada pelo RSM, executada pelo sequencer após a engine aprovar o saque
HCActionWithdrawOptionCréditos de opções são SystemCreditOption do RSM; depósitos usam depositOption
RsmCommandRebalanceHLOrder assinada pelo RSM (IOC reduce-only)
RsmCommandRepayHLSendAsset assinada pelo RSM para a Exchange
  • Funções de ordem legadas. placeCoreOrders, cancelCoreOrders e cancelCoreOrdersByCloid usavam codificação MsgPack e o domínio CoreSignatures ("Exchange", chain ID 1337). Foram removidas.
  • nextNonce. O contador on-chain nextNonce[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​

  1. Chaves: mantenha a chave do manager em uma carteira de hardware. API wallets só assinam ordens e cancelamentos; use chaves separadas por sistema.
  2. Replay de nonce: nunca reutilize um nonce. Controle os nonces off-chain e incremente de forma atômica.
  3. Domínio: sempre assine com chain ID 999 na mainnet (998 na testnet) e confira o separador que você calculou com a tabela acima.
  4. Verifique o que você assina: chame POST /v1/actions/{action}/typed-data e compare com seu próprio encoder antes de assinar com uma carteira de hardware.
  5. 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.
  6. 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​