Diese Seite wurde maschinell übersetzt. Das englische Original ist maßgeblich. Auf Englisch lesen →
Zum Hauptinhalt springen

EIP-712-Signierung

Diese Seite ist die Referenz auf Feldebene für jede EIP-712-Nachricht, die Hypercall verifiziert: die drei Signierdomänen für Direktiven (API-Wallet, Manager, RSM), die rein Off-Chain verarbeiteten Perp-Nachrichten, die die API-Wallet-Domäne mitnutzen, sowie die eigenständige Domäne Physical Covered Call Quote. Options-Orders über die REST-API verwenden eine andere Domäne, Hypercall; siehe Authentifizierung & Signierung.

Alle Angaben hier wurden gegen die auf dem HyperEVM-Mainnet (Chain-ID 999) deployten Contracts geprüft: Exchange 0.6.1 unter 0xE6b7FaA216cabb2b38B392f577C9c826378b2240 und Account 0.2.4. Die unten aufgeführten Domain-Separatoren und Typehashes sind in diesem deployten Bytecode eingebettet.

Überblick​

Eine Direktive ist eine einzelne Aktion gegen einen Account, die Off-Chain signiert und vom Sequencer von Hypercall über Exchange.executeUserDirective oder Exchange.executeRsmDirective On-Chain eingereicht wird. Der Account stellt den Signierer aus dem EIP-712-Digest wieder her und prüft die Autorisierung:

  1. API-Wallet: eine Adresse, die mit hc_update_api_wallet auf dem Account registriert wurde (Account.isApiWalletActive). Signiert Orders und Stornierungen.
  2. Manager: der Eigentümer des Accounts (Account.manager). Signiert Änderungen an API-Wallets, Asset-Überweisungen und Änderungen des Account-Modus.
  3. RSM-Signierer: protokollkontrolliert (Exchange.rsmSigner). Signiert Gutschriften, Auszahlungen, Liquidationsdirektiven und Reduce-only-Recovery-Orders. Nutzer signieren diese niemals.

Kodierung von Direktiven​

On-Chain ist eine Direktive abi.encodePacked(account, nonce, version, id, data):

BytesFeldBedeutung
20accountDie Account-Adresse (address)
8nonceDie Nonce des Signierers (uint64)
1versionAktionsfamilie
3idAktions-ID innerhalb der Familie
Restdataabi.encode des inneren Aktions-Structs
VersionFamilieAktions-IDs
0HyperCall (HC)2 API-Wallet aktualisieren. 1 (Option übertragen) ist reserviert und wird abgelehnt.
1HyperLiquid (HL)1 Limit-Order, 9 API-Wallet hinzufügen, 10 Stornierung per oid, 11 Stornierung per cloid, 13 Asset senden, 16 Abstraktion setzen
255System1 Token gutschreiben, 2 Option gutschreiben, 3 Liquidation starten, 4 Liquidation beenden, 5 Token auszahlen

Sie erstellen diesen Byte-String nicht selbst. Signieren Sie die typisierten Daten und reichen Sie anschließend account, nonce, action und signature bei der API ein, die die Direktive kodiert.

Struktur der typisierten Daten​

Jede Direktive hat dieselbe äußere Struktur: die Account-Adresse, die Nonce des Signierers und ein inneres Aktions-Struct.

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

Der äußere Typ-String hängt die innere Typdefinition an, sodass der Typehash beide abdeckt. In EIP-712-Begriffen ist primaryType der äußere Name, types enthält beide Einträge und message ist { account, nonce, action }. Die Feldreihenfolge ist Teil des Typ-Strings und muss exakt übereinstimmen.

Unsignierte Funding-Einstiegspunkte​

Nicht jeder Funding-Aufruf ist eine EIP-712-Aktion. Diese Methoden sind direkte Transaktionen, die von der zahlenden Wallet oder dem Router gesendet werden:

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

depositUsdcFor ist bewusst unsigniert, da msg.sender lediglich der USDC-Zahler ist. Der gutgeschriebene Hypercall-Account ist das explizite Argument account und das Event-Feld UsdcDeposit.account. Router und Zaps können diese Methode aufrufen, daher dürfen Indexer und Backend-Dienste msg.sender nicht für die Zuordnung von Gutschriften verwenden.

depositOption verbrennt Options-Token von msg.sender und emittiert Deposit(account, msg.sender, token, amount) für den RSM-Indexer. Der Gutschriftpfad für Optionen ist eventgesteuert und verwendet keine Manager-, Agent- oder RSM-Signatur des Einzahlers.

Eigenständige Domäne: Physical Covered Call Quotes​

Physische Covered-Call-Quotes werden von der auf der gewählten Chain deployten Factory verifiziert. Sie verwenden weder den Exchange-Verifier noch dessen Nulladress-Domäne.

Domäne:

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

Signierer: der in PhysicalCoveredCallQuote.marketMaker kodierte Market Maker.

Kanonische verschachtelte Typen:

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)

Die Factory berechnet requestHash aus dem vollständigen verschachtelten Request neu, bevor sie den Signierer des Quotes wiederherstellt. Die Signatur bindet daher den Verkäufer, den Basiswert-Wrapper, die Anzahl der Wrapper-Anteile, den Strike, den Verfall, die Prämie, die Quote-Deadline, die Nonce, die Chain-ID und die Factory-Adresse. Settlement-Token und Dezimalstellen sind maßgebliche Factory-Konfiguration und keine separat signierten Werte. Pyth ist in dieser orakellosen Generation nicht vorhanden. Sowohl der Quote-Digest als auch die Maker-Nonce werden verbraucht, wenn der Verkäufer einen Vault finanziert.

Nur der im Request kodierte Verkäufer kann den signierten Quote einreichen. Das Funding mintet das Writer-Claim-NFT an den Verkäufer und das Long-Options-NFT an den quotierenden Market Maker, sofern dieser Maker ein zulässiger Empfänger ist, während die optionale Käufer-Allowlist aktiviert ist. Eine gültige Signatur autorisiert das Funding, nicht die Ausübung.

Nur der aktuelle Eigentümer des Long-Options-NFTs darf die Ausübung aufrufen. Diese Owner-only-Regel verhindert, dass ein ERC-721-Operator das Settlement-Token-Allowance des Eigentümers verbraucht. Ein genehmigter Operator darf das NFT weiterhin nach den Standard-ERC-721-Regeln übertragen, wodurch das wirtschaftliche Recht an einen zulässigen Empfänger übergeht, solange das Käufer-Gate aktiviert ist. Eine erfolgreiche Ausübung zieht den Strike-Betrag vom aufrufenden Eigentümer ein, liefert den Basiswert an diesen Eigentümer und verbrennt das Long-Options-NFT.

EIP-712-Domain-Separatoren​

Die drei Direktiven-Domänen verwenden dieselbe Struktur und unterscheiden sich nur in name. Der verifyingContract ist die Nulladresse, daher ist dieselbe Signatur für jeden Account auf der Chain gültig, und erst die Account-Adresse innerhalb der Nachricht bindet sie an einen Account.

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

Der Domänentyp ist EIP712Domain(string name,string version,uint256 chainId,address verifyingContract).

Chain-IDs: Mainnet 999, Testnet 998. Der Account wählt den Separator anhand der Chain, auf der er läuft, sodass eine Testnet-Signatur niemals auf dem Mainnet verifiziert wird.

DomänenameversionSigniererChainSeparator
API-WalletHypercallApiSign1API-Wallet9990x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb
API-WalletHypercallApiSign1API-Wallet9980x339bee4c00da9a5361f687797205c8d03f323659f5d9dc9e0505b9437ddee25e
ManagerHypercallManagerSign1Manager9990xc9b5b0b8b0d9d7ba716326acbf795cfe431ef960a25a8f958d6569bea2f1516e
ManagerHypercallManagerSign1Manager9980xd1f76b6138be892c14b71b0569bdb049cb44f239d34c78ef1ffaacd2466f9f18
RSMHypercallRsmSign1RSM-Signierer9990x3d0cae2af623c614099dbadd67a1e1457fabde576aa270a70a57e39bf338a7be
RSMHypercallRsmSign1RSM-Signierer9980x650b282053fb61d3fd477bdc28f6434311fe905e27cc4ca643e87e802c45938c

Berechnen Sie den Separator selbst und vergleichen Sie ihn, bevor Sie irgendetwas signieren:

import { ethers } from "ethers";

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

Nachrichtenreferenz​

Matrix der Signierer und Endpunkte​

NachrichtDomäneSigniererEinreichen beiFührt aus
HLOrderAPIAPI-WalletPOST /v1/tee-perp/orders/submit oder POST /v1/actions/hl_limit_orderHyperliquid-Limit-Order
HLCancelAPIAPI-WalletPOST /v1/tee-perp/cancels/submit-by-oid oder POST /v1/actions/hl_cancel_by_oidStornierung per oid
HLCancelByCloidAPIAPI-WalletPOST /v1/tee-perp/cancels/submit oder POST /v1/actions/hl_cancel_by_cloidStornierung per cloid
HCPerpTriggerOrderAPIAPI-WalletPOST /v1/tee-perp/orders/submit-triggerNative Trigger-Order (nur TEE)
HCPerpOrderBatchAPIAPI-WalletPOST /v1/tee-perp/orders/submit-batchNativer Order-Batch (nur TEE)
HCPerpLeverageChangeAPIAPI-WalletPOST /v1/tee-perp/leverage/submitHebel-Änderung (nur TEE)
HCPerpScheduleCancelAPIAPI-WalletPOST /v1/tee-perp/schedule-cancel/submitTotmannschalter (nur TEE)
HCUpdateApiWalletManagerManagerPOST /v1/actions/hc_update_api_walletAPI-Wallet-Register des Account
HLAddApiWalletManagerManagerPOST /v1/actions/hl_add_api_walletAPI-Wallet-Genehmigung auf HyperCore
HLSendAssetManagerManagerPOST /v1/actions/hl_send_assetHyperCore-sendAsset vom Account
HLSetAbstractionManagerManagerPOST /v1/actions/hl_set_abstractionHyperCore-Account-Modus (nur Unified)
HCTransferOptionManagerManagerNicht akzeptiertReserviert, wird On-Chain abgelehnt
HLOrder, HLCancel, HLCancelByCloid, HLSendAssetRSMRSM-SigniererNur SequencerRecovery-Orders und Sweeps über den Account
System*RSMRSM-SigniererNur SequencerGutschriften, Auszahlungen, Liquidation über die Exchange

Alle Routen /v1/actions/{action} erwarten account, nonce, action und signature. POST /v1/actions/{action}/typed-data gibt die exakten zu signierenden typisierten Daten für diesen Request zurück und ist der einfachste Weg, Ihren Encoder zu überprüfen. GET /v1/directives/{directive_id} meldet das On-Chain-Ergebnis. Request-Schemas finden Sie in der API-Referenz.

Wire-Konventionen​

  • nonce und jedes Feld vom Typ uint64, uint128 oder uint256 sind JSON-Ganzzahlen bis 9007199254740991 oder Dezimal-Strings. Verwenden Sie oberhalb dieses Werts Strings.
  • signature ist ein 65-Byte-Hex-String mit 0x-Präfix (r || s || v). v darf 0, 1, 27 oder 28 sein.
  • bytes32-Felder sind 32-Byte-Hex mit 0x-Präfix. Adressen sind Hex mit Checksumme oder in Kleinbuchstaben.
  • Perp-Preise und -Größen sind die HyperCore-Ganzzahlen mit 1e8, zum Beispiel ist $50,000 gleich 5000000000000 und 0.001 Coins sind 100000.

API-Wallet-Direktiven (HypercallApiSign)​

Signiert von einer aktiven API-Wallet des Accounts. Verwenden Sie Chain-ID 999 und name HypercallApiSign.

Die Testvektoren verwenden einen Platzhalter-Account und eine feste Nonce, damit Sie Ihren Encoder Byte für Byte prüfen können. Der Digest ist keccak256(0x1901 || domainSeparator || directiveStructHash).

HLOrder​

Eine Hyperliquid-Limit-Order für den 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;
}

Kanonischer EIP-712-Typ:

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

Typehash: 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd. Signierer: API-Wallet. Aktion: Version 1, ID 1.

  • asset: der Hyperliquid-Asset-Index. GET /v1/tee-perp/markets listet die von Hypercall akzeptierten Perp-Märkte und ihre Indizes auf.
  • isBuy: true zum Kaufen, false zum Verkaufen.
  • limitPx, sz: Preis und Größe multipliziert mit 1e8.
  • reduceOnly: true, wenn die Order eine Position nur reduzieren darf.
  • encodedTif: ALO = 1, GTC = 2, IOC = 3. Jeder andere Wert wird abgelehnt.
  • cloid: Client-Order-ID, ungleich null. Sie verwenden sie später für die Stornierung per cloid.

Beispiel (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);

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd
Aktions-Struct-Hash0x0fd024c6bf8f132123e63a78d50008d8c39c52e5409ef6ca87a4eec8f6eabb41
Direktiven-Struct-Hash0xd32948ee1f249b96124a6acdb5845d09aad8228512098598de6858d5484fe703
Zu signierender Digest0xc3c42699092fe20c7dbc4205a1027f55c28d33a682a64bd3f04e40f1d28693f5

Der Testvektor verwendet isBuy: true, limitPx: 5000000000000, sz: 100000, reduceOnly: false, encodedTif: 2, asset: 0 und cloid gleich der Nonce.

Einreichen: POST /v1/tee-perp/orders/submit mit account, nonce, action und signature. Hypercall führt die Margin-Prüfung durch, anschließend signiert eine sichere Enclave die native Hyperliquid-Order und sendet sie mit angehängtem Hypercall-Builder-Code. Der Manager des Accounts muss diesen Builder zuvor mit Account.approveZeroFeeBuilder genehmigen; siehe Onboarding. Den vollständigen Ablauf finden Sie unter Perps.

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

Dieselbe signierte Nachricht wird auch unter POST /v1/actions/hl_limit_order akzeptiert, wo sie als On-Chain-Direktive kodiert und über Exchange.executeUserDirective und Account.performCoreAction ausgeführt wird.

HLCancel​

Storniert eine Order anhand der Hyperliquid-Order-ID. Der Wrapper ist HLCancel, das innere Struct ist 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. Signierer: API-Wallet. Aktion: Version 1, ID 10. Einreichen: POST /v1/tee-perp/cancels/submit-by-oid oder 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);

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85
Aktions-Struct-Hash0xa34e7bb8af0d099f9c48095924e53067bcb9b542a816445b96abebbc5646b727
Direktiven-Struct-Hash0x69d560ba5ef3e88459bde7fb8252e55dbc33627373c8f0cfcf8ef0868f59e097
Zu signierender Digest0x5046aba9fb33c55ce736faf63734ea66914f3f168ff0aff2229fa6f31fa9b330

Der Testvektor verwendet asset: 0 und oid: 123456789.

HLCancelByCloid​

Storniert eine Order anhand der Client-Order-ID, die Sie in HLOrder gesetzt haben.

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. Signierer: API-Wallet. Aktion: Version 1, ID 11. Einreichen: POST /v1/tee-perp/cancels/submit oder 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);

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5
Aktions-Struct-Hash0xfa4ab6440f946a6e279d90972d71223c768c01c8a91dc22703a6448dbcb966d0
Direktiven-Struct-Hash0x998efb01bb9c842eea80e8cc084b9e4e7ec13b2111790e1acbfec32e49060d9d
Zu signierender Digest0x56af82a6aa7fa50907a23c6cfe3aa556af5aa087b1157163ebf6ea0240e8d29d

Der Testvektor verwendet asset: 0 und cloid: 1760000000000.

Perp-Nachrichten nur für TEE​

Diese vier Nachrichten werden von der Hypercall-API verifiziert, nicht vom Account-Contract, da die Enclave sie nativ auf Hyperliquid ausführt und für sie keine On-Chain-Direktive existiert. Sie verwenden dieselbe Domäne HypercallApiSign und dieselbe API-Wallet-Autorisierung wie HLOrder (der Signierer muss eine aktive API-Wallet des Accounts sein, und der Account muss Portfolio-Margin nutzen). Ihre Typehashes sind nicht in den Contracts enthalten. Nonces sind Unix-Zeit in Millisekunden.

PerpOrderTerms​

HCPerpTriggerOrder und HCPerpOrderBatch betten beide dieses Struct ein. Eine Limit-Child-Order signiert ihr TIF-Byte mit triggerPx = 0, isMarket = false, tpsl = 0. Eine Trigger-Child-Order signiert encodedTif = 0, ein positives triggerPx und tpsl mit 1 (Take-Profit) oder 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​

Eine einzelne Stop-Loss- oder Take-Profit-Order, eingereicht bei POST /v1/tee-perp/orders/submit-trigger. Das Request-Feld action.orderType muss ein Trigger sein.

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

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x2d3104ab255275839aad254429e4be789f64a8d16b8e3e7d5f30a0db3c887b5c
Aktions-Struct-Hash0x285b3186be219b92d7159419288c0dce9bc4ad7bfc9536e009ebf24bd67f434c
Direktiven-Struct-Hash0xaa03e40b34b15e7e932ae827921930e7538387b596ef1040dbcc791e69021299
Zu signierender Digest0xc46aadc390b66c235af15e199e188ab23fb7f7f1b9237f6c2849c264c28d94da

Der Testvektor ist ein Reduce-only-Market-Stop-Loss-Verkauf: asset: 0, isBuy: false, limitPx: 4800000000000 (schlechtester Preis), sz: 100000, reduceOnly: true, encodedTif: 0, triggerPx: 4900000000000, isMarket: true, tpsl: 2, cloid: 1760000000001.

HCPerpOrderBatch​

Bis zu 100 Orders unter einer Gruppierung, eingereicht bei POST /v1/tee-perp/orders/submit-batch. Jede Order muss eine eigene cloid verwenden. grouping ist 0 (keine Gruppierung), 1 (normalTpsl) oder 2 (positionTpsl). Ein Batch zählt als eine Order-Platzierung gegenüber dem 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. Das Array orders wird als keccak256 der verketteten PerpOrderTerms-Struct-Hashes in Einreichungsreihenfolge kodiert.

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x9d4f467a44f4b0d39f234f3b91888546ce31dcbb67ce791550901b9042c38f8b
Hash des Orders-Arrays0x13fc75fcc69bf3b4ef7cdc3a0872c3cc1cf59440c74d366055109b6bd5ea7c98
Direktiven-Struct-Hash0x69d0b1131e386769823fe1ab3facbe8e6fc013f86a117cf95cb52b8ce2f274e0
Zu signierender Digest0x4b5cd34b1f254fdd9881b7674a3412807e16cade1f2ccc7a1e261482682fbd07

Der Testvektor ist grouping: 1 mit zwei Orders: ein GTC-Limit-Kauf (limitPx: 5000000000000, sz: 100000, cloid: 1760000000000), gefolgt vom Stop-Loss aus dem Trigger-Beispiel.

HCPerpLeverageChange​

Setzt den Hebel für ein Asset, eingereicht bei POST /v1/tee-perp/leverage/submit. leverage muss größer als null sein.

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

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0xe13845f0e6c16a5e1fc56b2d11fb0972faa2ec30b01e94d58c72147fa9b6a463
Aktions-Struct-Hash0x0e6e271dd56192d7fb1f37ea2eaffecfbbe2d1f79cac78dce6a6930bb8cc253e
Direktiven-Struct-Hash0xe04b169bbb0e20042308e5aad1036ce60eda75f484a4d6093dc60f2c2231129e
Zu signierender Digest0xb2a43487152a7cecc73d2b6b84d817a58dd02c559b05289a8d8e1b5c3d25e266

Der Testvektor setzt den Cross-Hebel auf 5x für asset: 0.

HCPerpScheduleCancel​

Der Totmannschalter von Hyperliquid: storniert jede offene Order zum Zeitpunkt time (Unix-Millisekunden, mindestens sieben Sekunden in der Zukunft). Eingereicht bei POST /v1/tee-perp/schedule-cancel/submit. Um eine geplante Stornierung aufzuheben, lassen Sie time im Request weg und signieren time = 0. Das Senden einer expliziten 0 wird abgelehnt.

struct PerpScheduleCancel {
uint64 time;
}

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

Typehash: 0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb
Aktions-Struct-Hash0x0a3ebfe48ef28a79beeee4d56e524f8a5280c38562efb697e7b1d63b3d475afc
Direktiven-Struct-Hash0xae64a13943a6a35b33aeb3095763b855c58c2119daf71e1e3228d8acf2645e8b
Zu signierender Digest0xa01806f47299010b5963a516562be3c3b44fed4f4a9e2e56c4bb601630146cdc

Der Testvektor plant eine Stornierung zum Zeitpunkt time: 1760000060000.

Vom Manager signierte vorbereitete Stornierung​

POST /v1/tee-perp/cancels/submit-prepared ist der vom Manager signierte Stornierungspfad. Er verwendet kein Struct für typisierte Daten. Der Manager signiert den Digest einer vorbereiteten nativen Hyperliquid-Stornierung, die als preparedRequest (Base64) mit managerSignature in kanonischer Low-s-Form übergeben wird, zusammen mit einer mit Zeitstempel versehenen authenticationSignature, die die Manager-Wallet authentifiziert. Das Request-Schema finden Sie in der API-Referenz.

Manager-Direktiven (HypercallManagerSign)​

Signiert vom Manager des Accounts. Verwenden Sie Chain-ID 999 und name HypercallManagerSign. Der Account verlangt signer == manager. Einreichen mit POST /v1/actions/{action}.

HCUpdateApiWallet​

Fügt die unter name im Account gespeicherte API-Wallet hinzu, ersetzt sie oder entfernt sie (addr = 0x0).

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. Aktion: Version 0, ID 2. Einreichen: POST /v1/actions/hc_update_api_wallet mit action von { "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);

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x8ebe7d19374200e5dc3ae838db74b370da95bd2b3a8aec9de85d2398dd4a9257
Aktions-Struct-Hash0x8b6c4a9db102e9d27c9a4069b39ba35e04948129359f0c15cd5103dd101ffce7
Direktiven-Struct-Hash0x830e291835ad182f290bc3d2bff09eaf9fd33acfbe44c6ad583218cd1a8232e5
Zu signierender Digest0x06589077544af449314db1fa8c7aac2d277cce9e833a04992d88161ede24cbe8

Der Testvektor verwendet name trading-bot (0x74726164696e672d626f74, rechts mit Nullen aufgefüllt) und addr 0x2222222222222222222222222222222222222222. Den vollständigen API-Wallet-Ablauf finden Sie unter Onboarding. Der Account emittiert ApiWalletUpdated(name, addr).

HLAddApiWallet​

Genehmigt eine Hyperliquid-API-Wallet für den Account auf 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. Aktion: Version 1, ID 9. Einreichen: POST /v1/actions/hl_add_api_wallet.

apiWalletName ist ein string, daher ist sein Struct-Feld keccak256(bytes(apiWalletName)). Ethers und viem erledigen dies für Sie.

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x71c0e0dfbddc3456015249946354324befde42b6851d1c9b26c6a29f2e0b1ac2
Aktions-Struct-Hash0xed32a441b0ee59c0252f5dff3411766289c9c35c19e3152b0b2b204176c2c7cd
Direktiven-Struct-Hash0xb990a3dfb4e8d96243539f8758b3a55249b217542bb4112f4f88ed67ec516ed9
Zu signierender Digest0x584886d020316085de0e0dec16331b8e990558be3e8fd004c47200abbebed518

Der Testvektor verwendet apiWalletAddress 0x2222222222222222222222222222222222222222 und apiWalletName hl-bot.

HLSendAsset​

Sendet Assets vom Account auf HyperCore an ein Ziel.

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. Aktion: Version 1, ID 13. Einreichen: 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);

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595
Aktions-Struct-Hash0x9b8c0290da19ea1069e14833023c4621a4f043354b36b4f17d4803b1fce6e656
Direktiven-Struct-Hash0xa0cb8a72188a61289fc2685c29a424605e0a2ee7b7af3e8cfee10e1c75153e08
Zu signierender Digest0x7c7037f27c659a1885f744778480e6847c5d08e98fb22517265ba708b6597d10

Der Testvektor sendet 5 USDC (amountWei: 500000000) von Perps (srcDex: 0) zu Spot (dstDex: 4294967295) mit destination gleich der Produktions-Exchange 0xE6b7FaA216cabb2b38B392f577C9c826378b2240.

HLSetAbstraction​

Setzt den HyperCore-Account-Modus des Accounts. Der Account akzeptiert nur user gleich sich selbst und abstraction = 2 (Unified Account); alles andere führt zu einem Revert. Portfolio-Margin setzt dies voraus.

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. Aktion: Version 1, ID 16. Einreichen: POST /v1/actions/hl_set_abstraction.

Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0xcf5fddf081e5f2a9a45aa87cb1a3c42e5aa20164566b1ad2369b6b1318eac786
Aktions-Struct-Hash0xef6c70a3c14b9e77c710c6b3b3ee681ca270ef884bd8a64fa4064a96f3dda84e
Direktiven-Struct-Hash0xdda9d0fe82b63c728c4ac42585d5998a04cabaed0f957a2cafdf31a754829c3d
Zu signierender Digest0xf49d7d8d74596e503d6a1bdfb26653533a12a5ba3816acd992d0bd4ef378f59d

Der Testvektor setzt user auf den Account und abstraction auf 2.

HCTransferOption (reserviert)​

Die Contracts definieren HCTransferOption(address account,uint64 nonce,TransferOption action)TransferOption(address recipient,address option,uint256 amountWei) (Typehash 0xa218e1158788b23987f954edc7a07659a03a03fe5ba981a5bbe44d7a146e0819, Aktionsversion 0, ID 1), ihm ist jedoch kein Signierertyp zugeordnet. Der Account führt einen Revert mit Account__UserDirectiveNotSupported aus, und die API lehnt hc_transfer_option ab. Signieren Sie diese Nachricht nicht. Verschieben Sie Options-Token stattdessen mit depositOption und Auszahlungen.

Manager-Transaktionen ohne Signatur​

Einige Manager-Aktionen sind direkte Account-Aufrufe und keine EIP-712-Nachrichten: Account.approveZeroFeeBuilder(builder) genehmigt einen Hyperliquid-Builder mit einer maximalen Gebühr von 0 % und ist einmalig vor der ersten Perp-Order erforderlich (siehe Onboarding). Account.transferTo(recipient, token, amount) verschiebt Token auf HyperEVM aus dem Account. Beide erfordern msg.sender == manager und führen zu einem Revert, solange sich der Account in Liquidation befindet.

RSM-Direktiven (HypercallRsmSign)​

Signiert vom RSM-Signierer und eingereicht vom Sequencer. Sie schreiben Einzahlungen gut, verarbeiten Auszahlungen, starten und beenden Liquidationen und platzieren Reduce-only-IOC-Recovery-Orders. Market Maker und Nutzer signieren oder reichen sie nicht ein; sie sind dokumentiert, damit Sie nachprüfen können, was das Protokoll mit einem Account tun darf. Verwenden Sie Chain-ID 999 und name HypercallRsmSign. Die Exchange prüft signer == rsmSigner (derzeit 0x502E7fAbF34E84EeB115C34FE947b79A94dF886E auf dem Mainnet), und der Aufrufer muss SEQUENCER_ROLE besitzen.

RSM-Orders und Sweeps (vom Account ausgeführt)​

Diese verwenden die HL-Structs unter der RSM-Domäne wieder, daher sind die Typehashes identisch mit denen für API und Manager, und nur der Domain-Separator unterscheidet sich. Der Account erzwingt zusätzliche Einschränkungen und führt sie auch während einer Liquidation aus.

NachrichtTypehashVom Account erzwungene Einschränkung
HLOrder0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707ddencodedTif muss IOC (3) sein, und die Order muss reduceOnly sein oder ein Spot-Verkauf gegen USDC (Spot-Asset-IDs 10000 bis 99999), limitiert auf höchstens 5 % unter dem HyperCore-Spotpreis
HLCancel0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85Keine
HLCancelByCloid0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5Keine
HLSendAsset0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595destination muss die Exchange sein

RSM-HLOrder-Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd
Aktions-Struct-Hash0x39b4e0699f382aaad23f04740034e7c5581ba918139d2db63fbf586cc447e7db
Direktiven-Struct-Hash0xe6dde5ad6d310b5ebb83c09ec28ee5568700473b885bb483b7437dca202af4f3
Zu signierender Digest0x57afa1e810804e768c05a467aa88ede15fdceedae5aaa840adff61a613aca469

Der RSM-HLOrder-Vektor ist ein Reduce-only-IOC-Verkauf (isBuy: false, limitPx: 4800000000000, sz: 100000, reduceOnly: true, encodedTif: 3, cloid gleich der Nonce). Exchange.executeRsmDirective verifiziert die Signatur und leitet die Aktion an den Account weiter.

Systemaktionen (von der Exchange ausgeführt)​

Version 255. Jeder Wrapper ist System<Action>(address account,uint64 nonce,<Action> action)<Action>(...).

WrapperInnerer TypTypehash
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

Vollständige äußere Typ-Strings:

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 schreibt dem Account Spot- oder Perp-Token von HyperCore gut. amountWei muss ungleich null sein, und der Account muss auf HyperCore aktiviert sein.
  • SystemCreditOption mintet Options-Token an den Account und deployt bei Bedarf das Options-Paar. underlying ist ein OpenZeppelin-ShortString-Wort: ASCII linksbündig mit der Byte-Länge im letzten Byte (BTC ist 0x42544300...03). Nicht-kanonische Kodierungen führen zu einem Revert.
  • SystemStartLiquidation zeichnet die Auktionsparameter auf und sperrt den Account. marginNeeded muss ungleich null sein.
  • SystemStopLiquidation verlangt, dass startTime dem aufgezeichneten Start entspricht, und gibt den Account an seinen Manager zurück.
  • SystemWithdrawToken stellt die Lieferung von Standard-USDC auf HyperCore aus dem eigenen Guthaben der Exchange in die Warteschlange. Es erfordert subAccount = 0, srcDex = 0, dstDex mit 0 oder 4294967295, token = 0 (USDC) sowie einen amountWei, der ein ganzzahliges Vielfaches der EVM-Einheit ist. Eine HyperEVM-Quittung allein ist kein Nachweis für die Lieferung auf HyperCore.

SystemCreditToken-Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052
Aktions-Struct-Hash0xc69d7c6e5c36c9789d990c6316eaff3be43980583806f41f8a8e6461b7114011
Direktiven-Struct-Hash0x7ffa37cef7e08d3a2dd5501a8648899d37bc09ebb25d148c124e12c5047476e1
Zu signierender Digest0x95f75e5ddb4837de3f578b8aa0d714d4b02672b18c4929e3d2dda4a266de8254

Der Vektor schreibt 5 USDC gut (srcDex und dstDex mit 4294967295, token: 0, amountWei: 500000000).

SystemCreditOption-Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae
Aktions-Struct-Hash0x4a8b563fc94d26c1da376145d5aa5d05f996232fcf9739ed0a662650e91861b6
Direktiven-Struct-Hash0x190b638f1a462469bf0d070248acfc86bbbb95ea8a9d3d97d33581c7d6bb5554
Zu signierender Digest0x86fb7c53bb7e139a4d5df7db2feae40e634efe09ea7509165d3cece75d75fce2

Der Vektor schreibt eine BTC-Call-Option gut (underlying: 0x42544300...03, expiry: 1761811200, strike: 80000, isCall: true, amountWei: 1000000000000000000).

SystemStartLiquidation-Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e
Aktions-Struct-Hash0x4cd6a7f0997eba84ef82eabd429a0d9ca80e55bd6d89d2e67eda9970d87ec803
Direktiven-Struct-Hash0x84f18dc2577978d7890c9eb269fd787d99de37039b3a08e24745398feffbd0c5
Zu signierender Digest0xcc72c0e7829938c9ca0a4515d759f94cc96d2f24cd51a134a430f215ed5f5d4b

Der Vektor verwendet equity: -1500000000 und marginNeeded: 20000000000 (beide USDC mit sechs Dezimalstellen).

SystemStopLiquidation-Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3
Aktions-Struct-Hash0x1d900a795b328bd5fa734bd6d7f74634b98ca66eb5e45322fb1ba6400564b62b
Direktiven-Struct-Hash0x977b9becdd26830f2cdf70ab40f72f24490fe6ed45822d1fc8c84120e9a46f40
Zu signierender Digest0xbe65f82782b14dba42e334e32dd7dcc6bf14c96824523723a186a7381f8f12af

Der Vektor verwendet startTime: 1760000000.

SystemWithdrawToken-Testvektor (Account 0x1111111111111111111111111111111111111111, Nonce 1760000000000, Chain 999):

SchrittWert
Typehash0x634b866e9a922bb846e297973c7a456e641b88f4e97493da9b222084d799c883
Aktions-Struct-Hash0x10bd8d4372a09e613a6b4fb7018fcccde857ebf6cc3327d6c9a3c0f81515a076
Direktiven-Struct-Hash0x86680427965513c65a7a170730b9f4fb2e2b40e22cd18338cb004b6a7872ada2
Zu signierender Digest0x65cc392038decb9ccdc23b0a4a1cfbe657d3417f8cd9ebf2319b3172fb7d885c

Der Vektor zahlt 5 USDC (amountWei: 500000000) an destination 0x1111111111111111111111111111111111111111 aus, mit srcDex: 0, dstDex: 0, token: 0.

Nonces​

Jeder Signierer hat einen unabhängigen Nonce-Raum, der an drei Stellen verfolgt wird.

  • Account-Contract: eine Bitmap pro Signierer. Account.isNonceUsed(signer, nonce) gibt zurück, ob eine Nonce verbraucht wurde. Eine Nutzer-Direktive führt bei Wiederverwendung zu einem Revert mit Account__NonceAlreadyUsed. Es gibt kein nextNonce; Lücken sind erlaubt, und die Reihenfolge spielt On-Chain keine Rolle.
  • Exchange-Contract: eine Bitmap für den RSM-Signierer, abrufbar mit Exchange.isNonceUsed(signer, nonce).
  • Engine: speichert die 100 höchsten Nonces pro Signierer. Eine neue Nonce darf nicht in der Menge enthalten sein, muss die kleinste gespeicherte Nonce übersteigen, sobald die Menge voll ist, und muss strikt innerhalb von zwei Tagen vor und einem Tag nach der Serverzeit in Millisekunden liegen.

Verwenden Sie die aktuelle Unix-Zeit in Millisekunden als Nonce-Ausgangswert und erhöhen Sie sie pro Signierer. Zwei Requests, die von derselben Wallet in derselben Millisekunde signiert werden, benötigen unterschiedliche Nonces, führen Sie daher einen Zähler. Bei den TEE-Perp-Routen ist die Nonce zugleich der Zeitanker des Requests, verwenden Sie dort also echte Millisekunden-Zeitstempel statt kleiner Ganzzahlen.

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

Ablauf der Signaturverifizierung​

  1. Off-Chain: Der Signierer erstellt den EIP-712-Digest (0x1901 || domainSeparator || structHash) und signiert ihn.
  2. API: Hypercall stellt den Signierer wieder her, prüft, ob es sich um eine aktive API-Wallet oder den Manager handelt, führt bei Orders die Margin-Prüfung der Engine durch und stellt die Direktive anschließend in die Warteschlange. Die Antwort meldet den tatsächlichen Verarbeitungsstand, Ablehnungsdetails und den Transaktions-Hash.
  3. Sequencer: reicht Exchange.executeUserDirective(directive, signature) ein. Die Exchange prüft, ob der Account existiert, und leitet an Account.executeUserDirective weiter.
  4. Account: rekonstruiert den Digest aus der eigenen Adresse, der Nonce und der Aktion, stellt den Signierer mit dem API- oder Manager-Separator für diese Aktion wieder her, prüft die Autorisierung, verbraucht die Nonce und führt dann aus. HL-Aktionen gehen an den HyperCore-CoreWriter. HC-Aktionen aktualisieren das API-Wallet-Register.
  5. Client: fragt GET /v1/directives/{directive_id} nach dem finalen Status ab.

Die TEE-Perp-Routen enden nach dem API-Schritt: Die Enclave, nicht der Account, führt die Order auf Hyperliquid aus.

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

Veraltet und entfernt​

Diese Bestandteile erschienen in früheren Versionen dieser Seite und sind nicht mehr Teil des deployten Systems. Sie sind aufgeführt, damit darauf aufbauende Integrationen migriert werden können.

  • Processor- und ActionCaster-Kodierung. Der Processor-Contract und die ActionCaster-Nachrichtenkodierung wurden in Exchange 0.2.0 (Februar 2026) entfernt. Account-Direktiven laufen jetzt über Exchange.executeUserDirective und CoreWriter. Die deployte Exchange 0.6.1 enthält keinen der alten Einstiegspunkte.
  • Exchange-Einstiegspunkte mit eigenen Structs. hlRequestOrder, hlRequestCancel, hlRequestCancelByCloid, hlActionSendAsset, hcActionWithdrawToken, hcActionWithdrawOption, rsmCommandRebalance und rsmCommandRepay existieren nicht mehr. Ihre Ersatzlösungen:
Entfernte NachrichtErsatz
HLRequestCancel (Batch aus HLCancel{asset,oid} plus Nonce)HLCancel mit einem CancelOrderByOid pro Direktive
HLRequestCancelByCloidHLCancelByCloid mit einem CancelOrderByCloid pro Direktive
HLActionSendAsset (account, nonce, destination, srcDex, dstDex, token, amountWei)HLSendAsset mit SendAsset, das subAccount ergänzt
HCActionWithdrawTokenRSM-signiertes SystemWithdrawToken, vom Sequencer ausgeführt, nachdem die Engine die Auszahlung genehmigt hat
HCActionWithdrawOptionOptions-Gutschriften sind RSM-SystemCreditOption; Einzahlungen verwenden depositOption
RsmCommandRebalanceRSM-signiertes HLOrder (Reduce-only IOC)
RsmCommandRepayRSM-signiertes HLSendAsset an die Exchange
  • Legacy-Order-Funktionen. placeCoreOrders, cancelCoreOrders und cancelCoreOrdersByCloid verwendeten eine MsgPack-Kodierung und die Domäne CoreSignatures ("Exchange", Chain-ID 1337). Sie wurden entfernt.
  • nextNonce. Der On-Chain-Zähler nextNonce[signer] existiert nicht mehr. Nur die Bitmap der verwendeten Nonces (isNonceUsed) bleibt bestehen.
  • Als TBD markierte Mainnet-Separatoren. Frühere Fassungen führten die Mainnet-Separatoren für Manager und RSM als TBD. Alle drei sind festgelegt und oben aufgeführt.
  • HCTransferOption. Definiert, aber nie aktiviert; siehe oben.

Sicherheitshinweise​

  1. Schlüssel: Bewahren Sie den Manager-Schlüssel auf einer Hardware-Wallet auf. API-Wallets signieren nur Orders und Stornierungen; verwenden Sie separate Schlüssel pro System.
  2. Nonce-Replay: Verwenden Sie niemals eine Nonce erneut. Verfolgen Sie Nonces Off-Chain und erhöhen Sie sie atomar.
  3. Domäne: Signieren Sie auf dem Mainnet immer mit Chain-ID 999 (998 auf dem Testnet) und prüfen Sie Ihren berechneten Separator gegen die obige Tabelle.
  4. Prüfen Sie, was Sie signieren: Rufen Sie POST /v1/actions/{action}/typed-data auf und vergleichen Sie das Ergebnis mit Ihrem eigenen Encoder, bevor Sie mit einer Hardware-Wallet signieren.
  5. Die On-Chain-Verifizierung ist maßgeblich: Die API prüft Signaturen vorab, aber der Account verifiziert jede Direktive On-Chain erneut. Werten Sie eine Bestätigung der API nicht als Ausführung.
  6. Manager vs. API-Wallet: Manager kontrollieren Eigentum, API-Wallets und Asset-Bewegungen. API-Wallets signieren nur Handelsnachrichten. Verwenden Sie separate Schlüssel.

Referenzen​