이 페이지는 자동 번역되었습니다. 영어 원문이 정본입니다. 영어로 읽기 →
메인 콘텐츠로 건너뛰기

EIP-712 서명

이 페이지는 Hypercall이 검증하는 모든 EIP-712 메시지에 대한 필드 단위 레퍼런스입니다. 세 가지 디렉티브 서명 도메인(API 지갑, Manager, RSM), API 지갑 도메인을 공유하는 오프체인 전용 퍼프 메시지, 그리고 독립형 Physical Covered Call Quote 도메인을 다룹니다. REST API의 옵션 주문은 별도의 도메인인 Hypercall을 사용합니다. 인증 및 서명을 참고하십시오.

이 페이지의 모든 내용은 HyperEVM 메인넷(체인 ID 999)에 배포된 컨트랙트를 기준으로 검증되었습니다. 대상은 0xE6b7FaA216cabb2b38B392f577C9c826378b2240에 배포된 Exchange 0.6.1과 Account 0.2.4입니다. 아래의 도메인 구분자(domain separator)와 타입해시는 배포된 바이트코드에 내장되어 있습니다.

개요​

디렉티브는 하나의 Account에 대한 하나의 작업으로, 오프체인에서 서명되고 Hypercall의 시퀀서가 Exchange.executeUserDirective 또는 Exchange.executeRsmDirective를 통해 온체인에 제출합니다. Account는 EIP-712 다이제스트에서 서명자를 복원하고 권한을 확인합니다.

  1. API 지갑: hc_update_api_wallet으로 Account에 등록된 주소입니다(Account.isApiWalletActive). 주문과 취소에 서명합니다.
  2. Manager: Account 소유자입니다(Account.manager). API 지갑 변경, 자산 전송, 계정 모드 변경에 서명합니다.
  3. RSM 서명자: 프로토콜이 관리합니다(Exchange.rsmSigner). 입금 반영, 출금, 청산 디렉티브, 감소 전용(reduce-only) 복구 주문에 서명합니다. 사용자는 이에 서명하지 않습니다.

디렉티브 인코딩​

온체인에서 디렉티브는 abi.encodePacked(account, nonce, version, id, data)입니다.

바이트필드의미
20accountAccount 주소 (address)
8nonce서명자의 논스 (uint64)
1version작업 계열
3id계열 내 작업 ID
나머지data내부 작업 구조체의 abi.encode
버전계열작업 ID
0HyperCall (HC)2 API 지갑 업데이트. 1(옵션 이전)은 예약되어 있으며 거부됩니다.
1HyperLiquid (HL)1 지정가 주문, 9 API 지갑 추가, 10 oid로 취소, 11 cloid로 취소, 13 자산 전송, 16 추상화 설정
255System1 토큰 입금 반영, 2 옵션 입금 반영, 3 청산 시작, 4 청산 중지, 5 토큰 출금

이 바이트 문자열을 직접 만들 필요는 없습니다. 타입 데이터에 서명한 뒤 account, nonce, action, signature를 API에 제출하면 API가 디렉티브를 인코딩합니다.

타입 데이터 구조​

모든 디렉티브는 동일한 외부 구조를 가집니다. Account 주소, 서명자의 논스, 그리고 하나의 내부 작업 구조체입니다.

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

외부 타입 문자열 뒤에 내부 타입 정의가 붙으므로 타입해시는 두 가지를 모두 포함합니다. EIP-712 용어로 primaryType은 외부 이름이고, types에는 두 항목이 모두 들어가며, message는 { account, nonce, action }입니다. 필드 순서는 타입 문자열의 일부이므로 정확히 일치해야 합니다.

서명이 필요 없는 자금 입금 진입점​

모든 자금 관련 호출이 EIP-712 작업인 것은 아닙니다. 다음 메서드는 지불하는 지갑이나 라우터가 직접 보내는 트랜잭션입니다.

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

depositUsdcFor는 msg.sender가 USDC 지불자일 뿐이므로 의도적으로 서명을 요구하지 않습니다. 입금이 반영되는 Hypercall 계정은 명시적인 account 인자이며 UsdcDeposit.account 이벤트 필드에 기록됩니다. 라우터와 zap이 이 메서드를 호출할 수 있으므로, 인덱서와 백엔드 서비스는 입금 귀속 판단에 msg.sender를 사용해서는 안 됩니다.

depositOption은 msg.sender의 옵션 토큰을 소각하고 RSM 인덱서를 위해 Deposit(account, msg.sender, token, amount)를 발생시킵니다. 옵션 입금 반영 경로는 이벤트 기반이며, 입금자의 manager, 에이전트, RSM 서명을 사용하지 않습니다.

독립형 도메인: 실물 인도형 커버드콜 호가​

실물 인도형 커버드콜 호가는 선택한 체인에 배포된 팩토리가 검증합니다. Exchange 검증자나 그 제로 주소 도메인을 사용하지 않습니다.

도메인:

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

서명자: PhysicalCoveredCallQuote.marketMaker에 인코딩된 마켓메이커입니다.

정규 중첩 타입:

AssetTerms(address underlyingWrapper)

OptionTerms(address seller,uint256 underlyingAmount,uint64 strikeX8,uint64 expiry)

PhysicalCoveredCallRequest(bytes32 rfqId,AssetTerms asset,OptionTerms option)AssetTerms(address underlyingWrapper)OptionTerms(address seller,uint256 underlyingAmount,uint64 strikeX8,uint64 expiry)

PhysicalCoveredCallQuote(bytes32 requestHash,bytes32 quoteId,address marketMaker,uint256 premiumSettlement,uint64 quoteDeadline,uint64 nonce)

팩토리는 호가 서명자를 복원하기 전에 전체 중첩 요청으로부터 requestHash를 다시 계산합니다. 따라서 서명은 매도자, 기초자산 래퍼, 래퍼 지분 수량, 행사가, 만기, 프리미엄, 호가 유효기한, 논스, 체인 ID, 팩토리 주소를 모두 바인딩합니다. 결제 토큰과 소수점 자릿수는 별도로 서명되는 값이 아니라 팩토리 설정이 기준입니다. 이 오라클 없는 세대에는 Pyth가 사용되지 않습니다. 매도자가 볼트에 자금을 넣을 때 호가 다이제스트와 마켓메이커 논스가 모두 소비됩니다.

요청에 인코딩된 매도자만 서명된 호가를 제출할 수 있습니다. 자금 투입 시 작성자 청구권(writer-claim) NFT는 매도자에게, 롱 옵션 NFT는 호가를 낸 마켓메이커에게 발행됩니다. 단, 선택적 매수자 허용 목록이 활성화된 경우 해당 마켓메이커가 적격 수령자여야 합니다. 유효한 서명은 자금 투입을 승인할 뿐 행사를 승인하지는 않습니다.

현재 롱 옵션 NFT 소유자만 행사를 호출할 수 있습니다. 이 소유자 전용 규칙은 ERC-721 오퍼레이터가 소유자의 결제 토큰 허용량(allowance)을 소비하는 것을 막습니다. 승인된 오퍼레이터는 표준 ERC-721 규칙에 따라 NFT를 이전할 수 있으며, 매수자 게이트가 활성화된 동안에는 경제적 권리가 적격 수령자에게 이전됩니다. 행사가 성공하면 호출자 겸 소유자로부터 행사가 대금을 가져오고, 해당 소유자에게 기초자산을 인도한 뒤 롱 옵션 NFT를 소각합니다.

EIP-712 도메인 구분자​

세 디렉티브 도메인은 같은 구조를 사용하며 name만 다릅니다. verifyingContract가 제로 주소이므로 같은 서명이 해당 체인의 모든 Account에서 유효하며, 메시지 내부의 Account 주소가 서명을 하나의 Account에 바인딩합니다.

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

도메인 타입은 EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)입니다.

체인 ID: 메인넷 999, 테스트넷 998. Account는 자신이 실행 중인 체인에 따라 구분자를 선택하므로 테스트넷 서명은 메인넷에서 절대 검증되지 않습니다.

도메인nameversion서명자체인구분자
API 지갑HypercallApiSign1API 지갑9990x462ae8a3a67da57ddd088e60be368536f992b8bf369d13e64e620c51993e5ebb
API 지갑HypercallApiSign1API 지갑9980x339bee4c00da9a5361f687797205c8d03f323659f5d9dc9e0505b9437ddee25e
ManagerHypercallManagerSign1Manager9990xc9b5b0b8b0d9d7ba716326acbf795cfe431ef960a25a8f958d6569bea2f1516e
ManagerHypercallManagerSign1Manager9980xd1f76b6138be892c14b71b0569bdb049cb44f239d34c78ef1ffaacd2466f9f18
RSMHypercallRsmSign1RSM 서명자9990x3d0cae2af623c614099dbadd67a1e1457fabde576aa270a70a57e39bf338a7be
RSMHypercallRsmSign1RSM 서명자9980x650b282053fb61d3fd477bdc28f6434311fe905e27cc4ca643e87e802c45938c

서명하기 전에 구분자를 직접 계산하여 비교하십시오.

import { ethers } from "ethers";

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

메시지 레퍼런스​

서명자 및 엔드포인트 매트릭스​

메시지도메인서명자제출 대상실행 내용
HLOrderAPIAPI 지갑POST /v1/tee-perp/orders/submit 또는 POST /v1/actions/hl_limit_orderHyperliquid 지정가 주문
HLCancelAPIAPI 지갑POST /v1/tee-perp/cancels/submit-by-oid 또는 POST /v1/actions/hl_cancel_by_oidoid로 취소
HLCancelByCloidAPIAPI 지갑POST /v1/tee-perp/cancels/submit 또는 POST /v1/actions/hl_cancel_by_cloidcloid로 취소
HCPerpTriggerOrderAPIAPI 지갑POST /v1/tee-perp/orders/submit-trigger네이티브 트리거 주문 (TEE 전용)
HCPerpOrderBatchAPIAPI 지갑POST /v1/tee-perp/orders/submit-batch네이티브 주문 배치 (TEE 전용)
HCPerpLeverageChangeAPIAPI 지갑POST /v1/tee-perp/leverage/submit레버리지 변경 (TEE 전용)
HCPerpScheduleCancelAPIAPI 지갑POST /v1/tee-perp/schedule-cancel/submit데드맨 스위치 (TEE 전용)
HCUpdateApiWalletManagerManagerPOST /v1/actions/hc_update_api_walletAccount API 지갑 레지스트리
HLAddApiWalletManagerManagerPOST /v1/actions/hl_add_api_walletHyperCore API 지갑 승인
HLSendAssetManagerManagerPOST /v1/actions/hl_send_assetAccount에서의 HyperCore sendAsset
HLSetAbstractionManagerManagerPOST /v1/actions/hl_set_abstractionHyperCore 계정 모드 (통합 계정만)
HCTransferOptionManagerManager허용되지 않음예약됨, 온체인에서 거부
HLOrder, HLCancel, HLCancelByCloid, HLSendAssetRSMRSM 서명자시퀀서 전용Account를 통한 복구 주문 및 스윕
System*RSMRSM 서명자시퀀서 전용Exchange를 통한 입금 반영, 출금, 청산

모든 /v1/actions/{action} 경로는 account, nonce, action, signature를 받습니다. POST /v1/actions/{action}/typed-data는 해당 요청에 대해 서명할 정확한 타입 데이터를 반환하므로, 인코더를 확인하는 가장 쉬운 방법입니다. GET /v1/directives/{directive_id}는 온체인 결과를 보고합니다. 요청 스키마는 API 레퍼런스에 있습니다.

전송 규약​

  • nonce와 모든 uint64, uint128, uint256 필드는 9007199254740991 이하의 JSON 정수 또는 10진수 문자열입니다. 그보다 큰 값은 문자열을 사용하십시오.
  • signature는 65바이트 0x 16진수 문자열(r || s || v)입니다. v는 0, 1, 27, 28 중 하나일 수 있습니다.
  • bytes32 필드는 0x 접두사가 붙은 32바이트 16진수입니다. 주소는 체크섬 형식 또는 소문자 16진수입니다.
  • 퍼프 가격과 수량은 HyperCore의 1e8 정수입니다. 예를 들어 $50,000은 5000000000000, 0.001코인은 100000입니다.

API 지갑 디렉티브 (HypercallApiSign)​

Account의 활성 API 지갑이 서명합니다. 체인 ID 999, name HypercallApiSign을 사용하십시오.

테스트 벡터는 플레이스홀더 계정과 고정 논스를 사용하므로 인코더를 바이트 단위로 확인할 수 있습니다. 다이제스트는 keccak256(0x1901 || domainSeparator || directiveStructHash)입니다.

HLOrder​

Account의 Hyperliquid 지정가 주문 하나입니다.

구조체:

struct LimitOrder {
uint32 asset;
bool isBuy;
uint64 limitPx;
uint64 sz;
bool reduceOnly;
uint8 encodedTif;
uint128 cloid;
}

struct HLOrder {
address account;
uint64 nonce;
LimitOrder action;
}

정규 EIP-712 타입:

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

타입해시: 0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd. 서명자: API 지갑. 작업: 버전 1, id 1.

  • asset: Hyperliquid 자산 인덱스입니다. GET /v1/tee-perp/markets에서 Hypercall이 허용하는 퍼프 시장과 그 인덱스를 확인할 수 있습니다.
  • isBuy: 매수는 true, 매도는 false입니다.
  • limitPx, sz: 가격과 수량에 1e8을 곱한 값입니다.
  • reduceOnly: 주문이 포지션을 줄이기만 할 수 있으면 true입니다.
  • encodedTif: ALO = 1, GTC = 2, IOC = 3. 그 외의 값은 거부됩니다.
  • cloid: 0이 아닌 클라이언트 주문 ID입니다. 이후 cloid로 취소할 때 사용합니다.

예시 (ethers.js):

const domain = {
name: "HypercallApiSign",
version: "1",
chainId: 999,
verifyingContract: ethers.ZeroAddress
};

const types = {
LimitOrder: [
{ name: "asset", type: "uint32" },
{ name: "isBuy", type: "bool" },
{ name: "limitPx", type: "uint64" },
{ name: "sz", type: "uint64" },
{ name: "reduceOnly", type: "bool" },
{ name: "encodedTif", type: "uint8" },
{ name: "cloid", type: "uint128" }
],
HLOrder: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "LimitOrder" }
]
};

const message = {
account: managedAccount,
nonce: selectedNonce,
action: {
asset: 0,
isBuy: true,
limitPx: 5000000000000n,
sz: 100000n,
reduceOnly: false,
encodedTif: 2,
cloid: selectedNonce
}
};

const signature = await apiWalletSigner.signTypedData(domain, types, message);

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd
작업 구조체 해시0x0fd024c6bf8f132123e63a78d50008d8c39c52e5409ef6ca87a4eec8f6eabb41
디렉티브 구조체 해시0xd32948ee1f249b96124a6acdb5845d09aad8228512098598de6858d5484fe703
서명할 다이제스트0xc3c42699092fe20c7dbc4205a1027f55c28d33a682a64bd3f04e40f1d28693f5

테스트 벡터는 isBuy: true, limitPx: 5000000000000, sz: 100000, reduceOnly: false, encodedTif: 2, asset: 0을 사용하며 cloid는 논스와 같습니다.

제출: account, nonce, action, signature와 함께 POST /v1/tee-perp/orders/submit. Hypercall이 증거금 검사를 수행한 뒤, 보안 엔클레이브가 Hypercall 빌더 코드를 붙인 네이티브 Hyperliquid 주문에 서명하여 전송합니다. Account manager는 먼저 Account.approveZeroFeeBuilder로 해당 빌더를 승인해야 합니다. 온보딩을 참고하십시오. 전체 흐름은 무기한 계약을 참고하십시오.

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

동일한 서명 메시지는 POST /v1/actions/hl_limit_order에서도 허용됩니다. 이 경로는 메시지를 온체인 디렉티브로 인코딩하며, Exchange.executeUserDirective와 Account.performCoreAction을 통해 실행됩니다.

HLCancel​

Hyperliquid 주문 ID로 주문 하나를 취소합니다. 래퍼는 HLCancel이고 내부 구조체는 CancelOrderByOid입니다.

struct CancelOrderByOid {
uint32 asset;
uint64 oid; // Order ID assigned by HyperCore
}

struct HLCancel {
address account;
uint64 nonce;
CancelOrderByOid action;
}
HLCancel(address account,uint64 nonce,CancelOrderByOid action)CancelOrderByOid(uint32 asset,uint64 oid)

타입해시: 0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85. 서명자: API 지갑. 작업: 버전 1, id 10. 제출: POST /v1/tee-perp/cancels/submit-by-oid 또는 POST /v1/actions/hl_cancel_by_oid.

const types = {
CancelOrderByOid: [
{ name: "asset", type: "uint32" },
{ name: "oid", type: "uint64" }
],
HLCancel: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "CancelOrderByOid" }
]
};

const message = {
account: managedAccount,
nonce: selectedNonce,
action: { asset: 0, oid: 123456789n }
};

const signature = await apiWalletSigner.signTypedData(domain, types, message);

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85
작업 구조체 해시0xa34e7bb8af0d099f9c48095924e53067bcb9b542a816445b96abebbc5646b727
디렉티브 구조체 해시0x69d560ba5ef3e88459bde7fb8252e55dbc33627373c8f0cfcf8ef0868f59e097
서명할 다이제스트0x5046aba9fb33c55ce736faf63734ea66914f3f168ff0aff2229fa6f31fa9b330

테스트 벡터는 asset: 0과 oid: 123456789를 사용합니다.

HLCancelByCloid​

HLOrder에 설정한 클라이언트 주문 ID로 주문 하나를 취소합니다.

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)

타입해시: 0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5. 서명자: API 지갑. 작업: 버전 1, id 11. 제출: POST /v1/tee-perp/cancels/submit 또는 POST /v1/actions/hl_cancel_by_cloid.

const types = {
CancelOrderByCloid: [
{ name: "asset", type: "uint32" },
{ name: "cloid", type: "uint128" }
],
HLCancelByCloid: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "CancelOrderByCloid" }
]
};

const message = {
account: managedAccount,
nonce: selectedNonce,
action: { asset: 0, cloid: 1760000000000n }
};

const signature = await apiWalletSigner.signTypedData(domain, types, message);

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5
작업 구조체 해시0xfa4ab6440f946a6e279d90972d71223c768c01c8a91dc22703a6448dbcb966d0
디렉티브 구조체 해시0x998efb01bb9c842eea80e8cc084b9e4e7ec13b2111790e1acbfec32e49060d9d
서명할 다이제스트0x56af82a6aa7fa50907a23c6cfe3aa556af5aa087b1157163ebf6ea0240e8d29d

테스트 벡터는 asset: 0과 cloid: 1760000000000을 사용합니다.

TEE 전용 퍼프 메시지​

이 네 가지 메시지는 Account 컨트랙트가 아니라 Hypercall API가 검증합니다. 엔클레이브가 Hyperliquid에서 네이티브로 실행하며 대응하는 온체인 디렉티브가 없기 때문입니다. HLOrder와 동일한 HypercallApiSign 도메인과 동일한 API 지갑 권한을 사용합니다(서명자는 Account의 활성 API 지갑이어야 하고, Account는 포트폴리오 증거금 모드여야 합니다). 이들의 타입해시는 컨트랙트에 포함되어 있지 않습니다. 논스는 밀리초 단위 Unix 시간입니다.

PerpOrderTerms​

HCPerpTriggerOrder와 HCPerpOrderBatch는 모두 이 구조체를 포함합니다. 지정가 하위 주문은 triggerPx = 0, isMarket = false, tpsl = 0과 함께 TIF 바이트에 서명합니다. 트리거 하위 주문은 encodedTif = 0, 양수 triggerPx, 그리고 tpsl 값 1(이익실현) 또는 2(손절)에 서명합니다.

struct PerpOrderTerms {
uint32 asset;
bool isBuy;
uint64 limitPx;
uint64 sz;
bool reduceOnly;
uint8 encodedTif;
uint64 triggerPx;
bool isMarket;
uint8 tpsl;
uint128 cloid;
}

HCPerpTriggerOrder​

손절 또는 이익실현 주문 하나로, POST /v1/tee-perp/orders/submit-trigger에 제출합니다. 요청의 action.orderType은 트리거여야 합니다.

struct HCPerpTriggerOrder {
address account;
uint64 nonce;
PerpOrderTerms order;
}
HCPerpTriggerOrder(address account,uint64 nonce,PerpOrderTerms action)PerpOrderTerms(uint32 asset,bool isBuy,uint64 limitPx,uint64 sz,bool reduceOnly,uint8 encodedTif,uint64 triggerPx,bool isMarket,uint8 tpsl,uint128 cloid)

타입해시: 0x2d3104ab255275839aad254429e4be789f64a8d16b8e3e7d5f30a0db3c887b5c

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x2d3104ab255275839aad254429e4be789f64a8d16b8e3e7d5f30a0db3c887b5c
작업 구조체 해시0x285b3186be219b92d7159419288c0dce9bc4ad7bfc9536e009ebf24bd67f434c
디렉티브 구조체 해시0xaa03e40b34b15e7e932ae827921930e7538387b596ef1040dbcc791e69021299
서명할 다이제스트0xc46aadc390b66c235af15e199e188ab23fb7f7f1b9237f6c2849c264c28d94da

테스트 벡터는 감소 전용 시장가 손절 매도입니다. asset: 0, isBuy: false, limitPx: 4800000000000(최악 가격), sz: 100000, reduceOnly: true, encodedTif: 0, triggerPx: 4900000000000, isMarket: true, tpsl: 2, cloid: 1760000000001.

HCPerpOrderBatch​

하나의 그룹 아래 최대 100개의 주문으로, POST /v1/tee-perp/orders/submit-batch에 제출합니다. 모든 주문은 서로 다른 cloid를 사용해야 합니다. grouping은 0(그룹 없음), 1(normalTpsl), 2(positionTpsl) 중 하나입니다. 배치는 속도 제한 상 주문 1건으로 계산됩니다.

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)

타입해시: 0x9d4f467a44f4b0d39f234f3b91888546ce31dcbb67ce791550901b9042c38f8b. orders 배열은 제출 순서대로 연결한 PerpOrderTerms 구조체 해시들의 keccak256으로 인코딩됩니다.

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x9d4f467a44f4b0d39f234f3b91888546ce31dcbb67ce791550901b9042c38f8b
주문 배열 해시0x13fc75fcc69bf3b4ef7cdc3a0872c3cc1cf59440c74d366055109b6bd5ea7c98
디렉티브 구조체 해시0x69d0b1131e386769823fe1ab3facbe8e6fc013f86a117cf95cb52b8ce2f274e0
서명할 다이제스트0x4b5cd34b1f254fdd9881b7674a3412807e16cade1f2ccc7a1e261482682fbd07

테스트 벡터는 grouping: 1이며 두 개의 주문으로 구성됩니다. GTC 지정가 매수(limitPx: 5000000000000, sz: 100000, cloid: 1760000000000) 다음에 트리거 예시의 손절 주문이 이어집니다.

HCPerpLeverageChange​

자산 하나의 레버리지를 설정하며, POST /v1/tee-perp/leverage/submit에 제출합니다. leverage는 0보다 커야 합니다.

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)

타입해시: 0xe13845f0e6c16a5e1fc56b2d11fb0972faa2ec30b01e94d58c72147fa9b6a463

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0xe13845f0e6c16a5e1fc56b2d11fb0972faa2ec30b01e94d58c72147fa9b6a463
작업 구조체 해시0x0e6e271dd56192d7fb1f37ea2eaffecfbbe2d1f79cac78dce6a6930bb8cc253e
디렉티브 구조체 해시0xe04b169bbb0e20042308e5aad1036ce60eda75f484a4d6093dc60f2c2231129e
서명할 다이제스트0xb2a43487152a7cecc73d2b6b84d817a58dd02c559b05289a8d8e1b5c3d25e266

테스트 벡터는 asset: 0에 교차 레버리지 5배를 설정합니다.

HCPerpScheduleCancel​

Hyperliquid의 데드맨 스위치로, time(Unix 밀리초, 최소 7초 이후)에 모든 미체결 주문을 취소합니다. POST /v1/tee-perp/schedule-cancel/submit에 제출합니다. 예약된 취소를 해제하려면 요청에서 time을 생략하고 time = 0에 서명하십시오. 명시적으로 0을 보내면 거부됩니다.

struct PerpScheduleCancel {
uint64 time;
}

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

타입해시: 0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0xf21b6881e346bbf4b8d82e8ea507cf487e58dfc08776ad662591be7d6065bdfb
작업 구조체 해시0x0a3ebfe48ef28a79beeee4d56e524f8a5280c38562efb697e7b1d63b3d475afc
디렉티브 구조체 해시0xae64a13943a6a35b33aeb3095763b855c58c2119daf71e1e3228d8acf2645e8b
서명할 다이제스트0xa01806f47299010b5963a516562be3c3b44fed4f4a9e2e56c4bb601630146cdc

테스트 벡터는 time: 1760000060000에 취소를 예약합니다.

Manager 서명 사전 준비 취소​

POST /v1/tee-perp/cancels/submit-prepared는 manager가 서명하는 취소 경로입니다. 타입 데이터 구조체를 사용하지 않습니다. Manager는 사전 준비된 네이티브 Hyperliquid 취소의 다이제스트에 서명합니다. 이는 preparedRequest(base64)로 전달되며, 정규 low-s 형식의 managerSignature와 manager 지갑을 인증하는 타임스탬프 포함 authenticationSignature가 함께 제공됩니다. 요청 스키마는 API 레퍼런스를 참고하십시오.

Manager 디렉티브 (HypercallManagerSign)​

Account manager가 서명합니다. 체인 ID 999, name HypercallManagerSign을 사용하십시오. Account는 signer == manager를 요구합니다. POST /v1/actions/{action}으로 제출합니다.

HCUpdateApiWallet​

Account에서 name 아래 저장된 API 지갑을 추가, 교체 또는 제거(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)

타입해시: 0x8ebe7d19374200e5dc3ae838db74b370da95bd2b3a8aec9de85d2398dd4a9257. 작업: 버전 0, id 2. 제출: action을 { "name": "0x...", "addr": "0x..." }로 하여 POST /v1/actions/hc_update_api_wallet.

const domain = {
name: "HypercallManagerSign",
version: "1",
chainId: 999,
verifyingContract: ethers.ZeroAddress
};

const types = {
UpdateApiWallet: [
{ name: "name", type: "bytes32" },
{ name: "addr", type: "address" }
],
HCUpdateApiWallet: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "UpdateApiWallet" }
]
};

const message = {
account: accountAddress,
nonce: selectedNonce,
action: {
name: ethers.encodeBytes32String("trading-bot"),
addr: apiWalletAddress
}
};

const signature = await managerSigner.signTypedData(domain, types, message);

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x8ebe7d19374200e5dc3ae838db74b370da95bd2b3a8aec9de85d2398dd4a9257
작업 구조체 해시0x8b6c4a9db102e9d27c9a4069b39ba35e04948129359f0c15cd5103dd101ffce7
디렉티브 구조체 해시0x830e291835ad182f290bc3d2bff09eaf9fd33acfbe44c6ad583218cd1a8232e5
서명할 다이제스트0x06589077544af449314db1fa8c7aac2d277cce9e833a04992d88161ede24cbe8

테스트 벡터는 name trading-bot(0x74726164696e672d626f74 뒤를 0으로 채움)과 addr 0x2222222222222222222222222222222222222222를 사용합니다. 전체 API 지갑 흐름은 온보딩을 참고하십시오. Account는 ApiWalletUpdated(name, addr)를 발생시킵니다.

HLAddApiWallet​

HyperCore에서 Account에 대한 Hyperliquid API 지갑을 승인합니다.

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)

타입해시: 0x71c0e0dfbddc3456015249946354324befde42b6851d1c9b26c6a29f2e0b1ac2. 작업: 버전 1, id 9. 제출: POST /v1/actions/hl_add_api_wallet.

apiWalletName은 string이므로 구조체 필드 값은 keccak256(bytes(apiWalletName))입니다. Ethers와 viem은 이를 자동으로 처리합니다.

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x71c0e0dfbddc3456015249946354324befde42b6851d1c9b26c6a29f2e0b1ac2
작업 구조체 해시0xed32a441b0ee59c0252f5dff3411766289c9c35c19e3152b0b2b204176c2c7cd
디렉티브 구조체 해시0xb990a3dfb4e8d96243539f8758b3a55249b217542bb4112f4f88ed67ec516ed9
서명할 다이제스트0x584886d020316085de0e0dec16331b8e990558be3e8fd004c47200abbebed518

테스트 벡터는 apiWalletAddress 0x2222222222222222222222222222222222222222와 apiWalletName hl-bot을 사용합니다.

HLSendAsset​

HyperCore의 Account에서 대상 주소로 자산을 전송합니다.

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)

타입해시: 0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595. 작업: 버전 1, id 13. 제출: POST /v1/actions/hl_send_asset.

const types = {
SendAsset: [
{ name: "destination", type: "address" },
{ name: "subAccount", type: "address" },
{ name: "srcDex", type: "uint32" },
{ name: "dstDex", type: "uint32" },
{ name: "token", type: "uint64" },
{ name: "amountWei", type: "uint64" }
],
HLSendAsset: [
{ name: "account", type: "address" },
{ name: "nonce", type: "uint64" },
{ name: "action", type: "SendAsset" }
]
};

const message = {
account: accountAddress,
nonce: selectedNonce,
action: {
destination: recipientAddress,
subAccount: ethers.ZeroAddress,
srcDex: 0,
dstDex: 0xFFFFFFFF, // spot
token: 0, // USDC
amountWei: 500000000n // 5 USDC
}
};

const signature = await managerSigner.signTypedData(domain, types, message);

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595
작업 구조체 해시0x9b8c0290da19ea1069e14833023c4621a4f043354b36b4f17d4803b1fce6e656
디렉티브 구조체 해시0xa0cb8a72188a61289fc2685c29a424605e0a2ee7b7af3e8cfee10e1c75153e08
서명할 다이제스트0x7c7037f27c659a1885f744778480e6847c5d08e98fb22517265ba708b6597d10

테스트 벡터는 destination을 프로덕션 Exchange 0xE6b7FaA216cabb2b38B392f577C9c826378b2240로 하여 퍼프(srcDex: 0)에서 현물(dstDex: 4294967295)로 5 USDC(amountWei: 500000000)를 전송합니다.

HLSetAbstraction​

Account의 HyperCore 계정 모드를 설정합니다. Account는 user가 자기 자신이고 abstraction = 2(통합 계정)인 경우만 허용하며, 그 외에는 되돌립니다(revert). 포트폴리오 증거금에는 이 설정이 필요합니다.

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)

타입해시: 0xcf5fddf081e5f2a9a45aa87cb1a3c42e5aa20164566b1ad2369b6b1318eac786. 작업: 버전 1, id 16. 제출: POST /v1/actions/hl_set_abstraction.

테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0xcf5fddf081e5f2a9a45aa87cb1a3c42e5aa20164566b1ad2369b6b1318eac786
작업 구조체 해시0xef6c70a3c14b9e77c710c6b3b3ee681ca270ef884bd8a64fa4064a96f3dda84e
디렉티브 구조체 해시0xdda9d0fe82b63c728c4ac42585d5998a04cabaed0f957a2cafdf31a754829c3d
서명할 다이제스트0xf49d7d8d74596e503d6a1bdfb26653533a12a5ba3816acd992d0bd4ef378f59d

테스트 벡터는 user를 Account로, abstraction을 2로 설정합니다.

HCTransferOption (예약됨)​

컨트랙트에는 HCTransferOption(address account,uint64 nonce,TransferOption action)TransferOption(address recipient,address option,uint256 amountWei)(타입해시 0xa218e1158788b23987f954edc7a07659a03a03fe5ba981a5bbe44d7a146e0819, 작업 버전 0, id 1)이 정의되어 있지만 할당된 서명자 유형이 없습니다. Account는 Account__UserDirectiveNotSupported로 되돌리며, API는 hc_transfer_option을 거부합니다. 이 메시지에 서명하지 마십시오. 옵션 토큰은 depositOption과 출금을 통해 이동하십시오.

서명 없는 Manager 트랜잭션​

일부 manager 작업은 EIP-712 메시지가 아니라 Account를 직접 호출합니다. Account.approveZeroFeeBuilder(builder)는 최대 수수료 0%로 Hyperliquid 빌더를 승인하며, 첫 퍼프 주문 전에 한 번 반드시 실행해야 합니다(온보딩 참고). Account.transferTo(recipient, token, amount)는 HyperEVM에서 Account 밖으로 토큰을 이동합니다. 두 작업 모두 msg.sender == manager를 요구하며, Account가 청산 중일 때는 되돌려집니다.

RSM 디렉티브 (HypercallRsmSign)​

RSM 서명자가 서명하고 시퀀서가 제출합니다. 입금 반영, 출금 처리, 청산 시작 및 중지, 감소 전용 IOC 복구 주문 제출을 수행합니다. 마켓메이커와 사용자는 이에 서명하거나 제출하지 않습니다. 프로토콜이 Account에 대해 수행할 수 있는 작업을 검증할 수 있도록 문서화되어 있습니다. 체인 ID 999, name HypercallRsmSign을 사용하십시오. Exchange는 signer == rsmSigner(현재 메인넷에서는 0x502E7fAbF34E84EeB115C34FE947b79A94dF886E)를 확인하며, 호출자는 SEQUENCER_ROLE을 보유해야 합니다.

RSM 주문 및 스윕 (Account가 실행)​

이 메시지들은 RSM 도메인 아래에서 HL 구조체를 재사용하므로, 타입해시는 API 및 manager의 것과 같고 도메인 구분자만 다릅니다. Account는 추가 제약 조건을 적용하며, 청산 중에도 이를 실행합니다.

메시지타입해시Account가 적용하는 제약 조건
HLOrder0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707ddencodedTif는 IOC(3)여야 하며, 주문은 reduceOnly이거나 HyperCore 현물 가격 대비 5% 이하로 낮게 제한된 USDC 대상 현물 매도(현물 자산 id 10000~99999)여야 합니다
HLCancel0x23c5529f34a875b6c0d11a6dfafdd945996dbdc5fbd1bdace2c2e0cf6a253a85없음
HLCancelByCloid0x10cbcfa56297fc737e4defee7b7937a52978ebbe5920e584317f7f25416836f5없음
HLSendAsset0x7feffdf7e7b191d5d27c2a209ca71c789289da73de203e99546abf9632860595destination은 Exchange여야 합니다

RSM HLOrder 테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0xe6facb816c5f9c321054ef43c7d8fb1ec750f65d630ec39c5c18119a6f4707dd
작업 구조체 해시0x39b4e0699f382aaad23f04740034e7c5581ba918139d2db63fbf586cc447e7db
디렉티브 구조체 해시0xe6dde5ad6d310b5ebb83c09ec28ee5568700473b885bb483b7437dca202af4f3
서명할 다이제스트0x57afa1e810804e768c05a467aa88ede15fdceedae5aaa840adff61a613aca469

RSM HLOrder 벡터는 감소 전용 IOC 매도입니다(isBuy: false, limitPx: 4800000000000, sz: 100000, reduceOnly: true, encodedTif: 3, cloid는 논스와 동일). Exchange.executeRsmDirective가 서명을 검증하고 작업을 Account로 전달합니다.

시스템 작업 (Exchange가 실행)​

버전 255. 각 래퍼는 System<Action>(address account,uint64 nonce,<Action> action)<Action>(...) 형식입니다.

래퍼내부 타입타입해시
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

전체 외부 타입 문자열:

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은 HyperCore의 현물 또는 퍼프 토큰을 Account에 반영합니다. amountWei는 0이 아니어야 하며, Account는 HyperCore에서 활성화되어 있어야 합니다.
  • SystemCreditOption은 Account에 옵션 토큰을 발행하며, 필요한 경우 옵션 페어를 배포합니다. underlying은 OpenZeppelin ShortString 워드로, ASCII를 왼쪽 정렬하고 마지막 바이트에 바이트 길이를 둡니다(BTC는 0x42544300...03). 정규 형식이 아닌 인코딩은 되돌려집니다.
  • SystemStartLiquidation은 경매 파라미터를 기록하고 Account를 잠급니다. marginNeeded는 0이 아니어야 합니다.
  • SystemStopLiquidation은 startTime이 기록된 시작 시각과 같아야 하며, Account를 manager에게 반환합니다.
  • SystemWithdrawToken은 Exchange 자체 잔고에서 HyperCore로의 Standard USDC 인도를 대기열에 넣습니다. subAccount = 0, srcDex = 0, dstDex는 0 또는 4294967295, token = 0(USDC), 그리고 EVM 단위의 정수배인 amountWei가 필요합니다. HyperEVM 영수증만으로는 HyperCore에서의 인도를 증명할 수 없습니다.

SystemCreditToken 테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0xe845f2049264182802994dae939dc8ac42d3ae543a7eeb530dd021428743f052
작업 구조체 해시0xc69d7c6e5c36c9789d990c6316eaff3be43980583806f41f8a8e6461b7114011
디렉티브 구조체 해시0x7ffa37cef7e08d3a2dd5501a8648899d37bc09ebb25d148c124e12c5047476e1
서명할 다이제스트0x95f75e5ddb4837de3f578b8aa0d714d4b02672b18c4929e3d2dda4a266de8254

이 벡터는 5 USDC를 반영합니다(srcDex와 dstDex는 4294967295, token: 0, amountWei: 500000000).

SystemCreditOption 테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x65aedd5af06882e1e62d752b43b72ec62a85cacf2ca59e8ec2affc57eed9d8ae
작업 구조체 해시0x4a8b563fc94d26c1da376145d5aa5d05f996232fcf9739ed0a662650e91861b6
디렉티브 구조체 해시0x190b638f1a462469bf0d070248acfc86bbbb95ea8a9d3d97d33581c7d6bb5554
서명할 다이제스트0x86fb7c53bb7e139a4d5df7db2feae40e634efe09ea7509165d3cece75d75fce2

이 벡터는 BTC 콜옵션 1계약을 반영합니다(underlying: 0x42544300...03, expiry: 1761811200, strike: 80000, isCall: true, amountWei: 1000000000000000000).

SystemStartLiquidation 테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x92b6a135a656e489c24fb5511684842b0ab3895c22b51e4910dee90a7d23511e
작업 구조체 해시0x4cd6a7f0997eba84ef82eabd429a0d9ca80e55bd6d89d2e67eda9970d87ec803
디렉티브 구조체 해시0x84f18dc2577978d7890c9eb269fd787d99de37039b3a08e24745398feffbd0c5
서명할 다이제스트0xcc72c0e7829938c9ca0a4515d759f94cc96d2f24cd51a134a430f215ed5f5d4b

이 벡터는 equity: -1500000000과 marginNeeded: 20000000000을 사용합니다(둘 다 소수점 6자리 USDC).

SystemStopLiquidation 테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0xe1af98778e9cfd1d1a679bb0b64b6dc8aa3fb152ff6469d0a81a1c7eb87a4bd3
작업 구조체 해시0x1d900a795b328bd5fa734bd6d7f74634b98ca66eb5e45322fb1ba6400564b62b
디렉티브 구조체 해시0x977b9becdd26830f2cdf70ab40f72f24490fe6ed45822d1fc8c84120e9a46f40
서명할 다이제스트0xbe65f82782b14dba42e334e32dd7dcc6bf14c96824523723a186a7381f8f12af

이 벡터는 startTime: 1760000000을 사용합니다.

SystemWithdrawToken 테스트 벡터 (계정 0x1111111111111111111111111111111111111111, 논스 1760000000000, 체인 999):

단계값
타입해시0x634b866e9a922bb846e297973c7a456e641b88f4e97493da9b222084d799c883
작업 구조체 해시0x10bd8d4372a09e613a6b4fb7018fcccde857ebf6cc3327d6c9a3c0f81515a076
디렉티브 구조체 해시0x86680427965513c65a7a170730b9f4fb2e2b40e22cd18338cb004b6a7872ada2
서명할 다이제스트0x65cc392038decb9ccdc23b0a4a1cfbe657d3417f8cd9ebf2319b3172fb7d885c

이 벡터는 srcDex: 0, dstDex: 0, token: 0으로 destination 0x1111111111111111111111111111111111111111에 5 USDC(amountWei: 500000000)를 출금합니다.

논스​

각 서명자는 독립적인 논스 공간을 가지며, 세 곳에서 추적됩니다.

  • Account 컨트랙트: 서명자별 비트맵입니다. Account.isNonceUsed(signer, nonce)는 논스가 소비되었는지 여부를 반환합니다. 사용자 디렉티브가 논스를 재사용하면 Account__NonceAlreadyUsed로 되돌려집니다. nextNonce는 없으며, 온체인에서는 간격이 허용되고 순서도 상관없습니다.
  • Exchange 컨트랙트: RSM 서명자용 비트맵으로, Exchange.isNonceUsed(signer, nonce)로 조회합니다.
  • 엔진: 서명자별로 가장 큰 논스 100개를 보관합니다. 새 논스는 이 집합에 없어야 하고, 집합이 가득 찬 경우 저장된 가장 작은 논스보다 커야 하며, 밀리초 단위 서버 시간 기준 2일 전부터 1일 후 사이의 범위 안에 엄격히 있어야 합니다.

현재 Unix 밀리초 시간을 논스 시드로 사용하고 서명자별로 증가시키십시오. 같은 지갑이 같은 밀리초에 서명한 두 요청은 서로 다른 논스가 필요하므로 카운터를 유지하십시오. TEE 퍼프 경로에서는 논스가 요청의 시간 기준점이기도 하므로, 작은 정수가 아닌 실제 밀리초 타임스탬프를 사용하십시오.

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

서명 검증 흐름​

  1. 오프체인: 서명자가 EIP-712 다이제스트(0x1901 || domainSeparator || structHash)를 구성하고 서명합니다.
  2. API: Hypercall이 서명자를 복원하고 활성 API 지갑 또는 manager인지 확인한 뒤, 주문의 경우 엔진 증거금 검사를 수행하고 디렉티브를 대기열에 넣습니다. 응답에는 실제 처리 단계, 거부 상세 정보, 트랜잭션 해시가 포함됩니다.
  3. 시퀀서: Exchange.executeUserDirective(directive, signature)를 제출합니다. Exchange는 Account가 존재하는지 확인하고 Account.executeUserDirective로 전달합니다.
  4. Account: 자신의 주소, 논스, 작업으로부터 다이제스트를 다시 구성하고, 해당 작업에 맞는 API 또는 manager 구분자로 서명자를 복원한 뒤, 권한을 확인하고 논스를 소비한 다음 실행합니다. HL 작업은 HyperCore CoreWriter로 전달됩니다. HC 작업은 API 지갑 레지스트리를 업데이트합니다.
  5. 클라이언트: 최종 상태를 확인하기 위해 GET /v1/directives/{directive_id}를 폴링합니다.

TEE 퍼프 경로는 API 단계 이후에서 끝납니다. Account가 아니라 엔클레이브가 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

지원 중단 및 제거된 항목​

다음 항목은 이 페이지의 이전 버전에 있었으나 더 이상 배포된 시스템의 일부가 아닙니다. 이를 기반으로 구축된 통합을 마이그레이션할 수 있도록 나열합니다.

  • Processor 및 ActionCaster 인코딩. Processor 컨트랙트와 ActionCaster 메시지 인코딩은 Exchange 0.2.0(2026년 2월)에서 제거되었습니다. Account 디렉티브는 이제 Exchange.executeUserDirective와 CoreWriter를 거칩니다. 배포된 Exchange 0.6.1에는 이전 진입점이 전혀 없습니다.
  • 자체 구조체를 가진 Exchange 진입점. hlRequestOrder, hlRequestCancel, hlRequestCancelByCloid, hlActionSendAsset, hcActionWithdrawToken, hcActionWithdrawOption, rsmCommandRebalance, rsmCommandRepay는 제거되었습니다. 대체 항목은 다음과 같습니다.
제거된 메시지대체 항목
HLRequestCancel (HLCancel{asset,oid} 배치와 논스)디렉티브당 CancelOrderByOid 하나를 가진 HLCancel
HLRequestCancelByCloid디렉티브당 CancelOrderByCloid 하나를 가진 HLCancelByCloid
HLActionSendAsset (account, nonce, destination, srcDex, dstDex, token, amountWei)subAccount가 추가된 SendAsset을 사용하는 HLSendAsset
HCActionWithdrawToken엔진이 출금을 승인한 후 시퀀서가 실행하는 RSM 서명 SystemWithdrawToken
HCActionWithdrawOption옵션 입금 반영은 RSM SystemCreditOption, 입금은 depositOption 사용
RsmCommandRebalanceRSM 서명 HLOrder (감소 전용 IOC)
RsmCommandRepayExchange로 보내는 RSM 서명 HLSendAsset
  • 레거시 주문 함수. placeCoreOrders, cancelCoreOrders, cancelCoreOrdersByCloid는 MsgPack 인코딩과 CoreSignatures 도메인("Exchange", 체인 ID 1337)을 사용했습니다. 이들은 제거되었습니다.
  • nextNonce. 온체인 nextNonce[signer] 카운터는 더 이상 존재하지 않습니다. 사용된 논스 비트맵(isNonceUsed)만 남아 있습니다.
  • TBD로 표시된 메인넷 구분자. 이전 문서에서는 manager 및 RSM 메인넷 구분자를 TBD로 표기했습니다. 세 가지 모두 확정되었으며 위에 나열되어 있습니다.
  • HCTransferOption. 정의되어 있지만 활성화된 적이 없습니다. 위 내용을 참고하십시오.

보안 고려사항​

  1. 키: manager 키는 하드웨어 지갑에 보관하십시오. API 지갑은 주문과 취소에만 서명하므로 시스템별로 별도의 키를 사용하십시오.
  2. 논스 재사용: 논스를 절대 재사용하지 마십시오. 오프체인에서 논스를 추적하고 원자적으로 증가시키십시오.
  3. 도메인: 메인넷에서는 항상 체인 ID 999(테스트넷은 998)로 서명하고, 계산한 구분자를 위 표와 대조하십시오.
  4. 서명 내용 확인: 하드웨어 지갑으로 서명하기 전에 POST /v1/actions/{action}/typed-data를 호출하여 자체 인코더 결과와 비교하십시오.
  5. 온체인 검증이 최종입니다: API가 서명을 사전 검사하지만, Account는 모든 디렉티브를 온체인에서 다시 검증합니다. API 응답을 실행 완료로 간주하지 마십시오.
  6. Manager와 API 지갑의 구분: manager는 소유권, API 지갑, 자산 이동을 제어합니다. API 지갑은 거래 메시지에만 서명합니다. 별도의 키를 사용하십시오.

참고 자료​