본문으로 건너뛰기
0%

Hyperliquid 주문 vs 거래 vs 체결

Uttam Singh headshot

작성자 Uttam Singh

2026년 10월 20일에 게시됨10분 읽기

Hyperliquid 주문 vs 거래 vs 체결

Hyperliquid에서 주문은 매수 또는 매도 지시이고, 거래는 두 주문 간의 매칭 한 건이며, 체결은 그 매칭에서 한 계정 쪽의 기록입니다. 모든 거래는 계정마다 하나씩, 정확히 두 건의 체결을 만듭니다. 이 가이드에서는 HyperCore의 각 레코드 페이로드, 이들을 조인하는 키, 그리고 프로덕션에서 대사를 깨뜨리는 실패 사례를 살펴봅니다.

세 레코드는 서로 다른 스트림으로 도착하고 변경되는 시점도 다르기 때문에, 이들을 같은 것으로 취급하는 코드는 점점 거래소와 어긋나게 됩니다. 아래 내용은 모두 실제 Hyperliquid 메인넷 데이터로 확인했으며, 이 가이드의 두 스크립트는 현재 공개 Hyperliquid API에서 그대로 실행됩니다.

주문, 거래, 체결의 차이는 무엇인가?

HyperCore는 Hyperliquid의 네이티브 거래소 엔진으로, HyperEVM 스마트 컨트랙트 환경과는 분리되어 있습니다. 완전한 온체인 오더북을 운영하므로 모든 주문 제출, 취소, 매칭이 블록에 기록됩니다.

세 레코드는 이 활동을 서로 다른 관점에서 기술합니다.

레코드
기술하는 내용
식별자
범위
스트림
주문 업데이트
주문 상태의 변경(open, filled, canceled, rejected)
oid
단일 계정
orderUpdates (네이티브), userOrderUpdates (Alchemy)
거래
한 마켓에서 매수자와 매도자 간에 일어난 매칭 한 건
tid
단일 마켓, 양쪽 계정
trades
체결
거래에서 한 계정 쪽의 기록(수수료와 PnL 포함)
tid 및 oid
단일 계정
userFills

거래는 매칭을 마켓 관점에서 본 것이므로 양쪽 계정을 모두 나열하고 수수료는 포함하지 않습니다. 체결은 같은 매칭을 계정 관점에서 본 것이므로, 해당 계정이 지불한 수수료, 체결 직전에 보유한 포지션, 그리고 체결을 발생시킨 주문을 담고 있습니다. 주문 업데이트는 주문 자체를 기술하며, 다음 섹션에서 보듯이 대부분의 개발자가 예상하는 것보다 훨씬 드물게 발생합니다.

트레이딩 봇이나 포트폴리오 트래커를 만들고 있다면, 실제로 실행된 내역의 기준(source of truth)은 체결이고, 아직 오더북에 대기 중인 주문의 기준은 주문 업데이트입니다.

주문 업데이트는 어떤 형태인가?

주문 업데이트는 주문 상태가 바뀔 때 발생합니다. 페이로드는 주문을 상태 레코드로 감쌉니다.

json
Copied
{ "status": "open", "statusTimestamp": 1780000000000, "hash": "0xabc...def", "order": { "oid": 12345, "coin": "BTC", "side": "B", "limitPx": "100000.0", "sz": "0.10", "origSz": "0.10", "orderType": "Limit", "tif": "Gtc", "reduceOnly": false, "isTrigger": false, "triggerPx": "0.0", "cloid": null } }

상태 추적에 가장 중요한 필드는 다음과 같습니다.

  • oid. 거래소가 부여한 주문 ID입니다. 체결이 이 값을 참조하므로, 주문과 그 실행 내역을 잇는 조인 키입니다.
  • origSz 및 sz. 주문 제출 시점의 수량과, 이 상태 레코드 시점에 아직 오더북에 남아 있는 수량입니다.
  • status. 새로운 상태입니다. 흔한 값은 open, filled, canceled, triggered이며, 그 밖에도 badAloPxRejected, reduceOnlyCanceled, selfTradeCanceled, liquidatedCanceled 같은 구체적인 거부 및 취소 사유가 길게 이어집니다.
  • tif. 주문 유효 조건(time in force)입니다. Gtc는 취소될 때까지 오더북에 남고, Alo(add liquidity only)는 스프레드를 넘어 즉시 체결될 경우 거부되며, Ioc(immediate or cancel)는 체결 가능한 만큼만 체결하고 나머지는 버립니다.
  • cloid. 클라이언트가 선택적으로 지정하는 주문 ID로, 주문을 시스템이 보낸 요청과 매칭할 때 유용합니다.

userOrderUpdates 레퍼런스는 노드 출력에서 관측된 모든 상태 값을 나열하면서, 이 목록이 전부는 아니라고 명시합니다. 알 수 없는 상태 문자열은 크래시로 이어지게 두지 말고, 로그를 남기고 조사할 최종 상태로 취급하세요.

주문 업데이트의 다음 세 가지 동작은 단순한 상태 머신을 깨뜨립니다.

부분 체결은 주문 업데이트를 만들지 않습니다. 실제 계정을 관찰해 보니, 부분 체결된 대기 주문은 open을 내보낸 뒤 하나 이상의 체결이 이어졌고, 최종 상태에 도달할 때까지 아무것도 내보내지 않았습니다. 이런 주문이 나중에 취소되면 canceled 레코드의 sz에 잔여 수량이 담깁니다. 미체결 주문의 실시간 잔여 수량이 필요하다면 체결로부터 계산하거나, 필요할 때 미체결 주문을 조회하세요.

filled 상태가 항상 전량 체결을 의미하지는 않습니다. 수량의 일부만 매칭된 Ioc 주문은 filled 상태와 0이 아닌 sz로 끝나는데, 이는 버려진 미체결 잔량입니다. 활발한 계정에서 45초 동안 수집한 샘플에서는 filled에 도달한 Ioc 주문 127건 중 72건에 여전히 잔량이 남아 있었습니다. 주문을 완료로 처리하기 전에 sz를 확인하세요.

hash 필드는 open일 때만 채워집니다. 취소 및 거부 레코드는 해시가 null이므로, 트랜잭션 해시는 주문 내역의 키로 쓸 수 없습니다.

거래는 어떤 형태인가?

trades 스트림은 한 마켓의 모든 매칭을 발행합니다. 각 레코드는 크기가 작습니다.

json
Copied
{ "coin": "ETH", "side": "A", "px": "2658.9", "sz": "1.0", "time": 1790608928951, "hash": "0xd8c5bd7a...25ae9e33", "tid": 825882878864874, "users": ["0x4cf1...e717", "0xe4f5...c0c4"] }

side는 테이커의 방향으로, A(ask)는 테이커가 매도했다는 뜻이고 B(bid)는 테이커가 매수했다는 뜻입니다. users는 항상 매수자를 먼저, 매도자를 두 번째로 나열하므로, side가 B이면 테이커는 users[0]이고 side가 A이면 users[1]입니다. 위 예시에서는 테이커가 매도했으므로 0xe4f5...c0c4가 테이커이고 0x4cf1...e717이 대기 중이던 매수자입니다.

테이커 주문 하나가 여러 대기 주문을 한 번에 소진하면 여러 건의 거래가 발생합니다. 각 거래는 고유한 tid를 가지며, 하나의 트랜잭션이 모두를 발생시켰기 때문에 같은 hash와 time을 공유합니다. 즉 hash는 거래가 아니라 트랜잭션을 식별합니다.

일부 거래는 전부 0으로 된 해시를 가집니다. 8개 마켓의 최근 거래 80건을 샘플링한 결과 7건의 해시가 0이었습니다. 저희가 추적한 한 건은 TWAP 슬라이스였는데, 이는 거래소가 새로 서명된 트랜잭션 없이 사용자를 대신해 실행하는 주문이며, Hyperliquid의 info 엔드포인트 문서에서도 TWAP 체결의 해시가 0임을 확인할 수 있습니다. 해시로 거래와 트랜잭션을 조인하는 코드는 이 경우를 처리해야 합니다.

거래 테이프, 거래량, 가격 차트 같은 마켓 전체 데이터에는 trades를 사용하세요. 특정 계정에 관한 것이라면 대신 체결을 구독하세요. 거래 레코드에는 수수료, 주문 ID, 포지션 맥락이 없기 때문입니다.

체결은 어떤 형태인가?

체결은 거래에서 한 계정 쪽의 기록입니다. 다음은 메인넷에서 가져온, 위 ETH 거래의 두 체결입니다.

json
Copied
[ { "coin": "ETH", "px": "2658.9", "sz": "1.0", "side": "B", "time": 1790608928951, "startPosition": "19.3599", "dir": "Open Long", "closedPnl": "0.0", "hash": "0xd8c5bd7a...25ae9e33", "oid": 559115773954, "crossed": false, "fee": "-0.079767", "tid": 825882878864874, "feeToken": "USDC", "twapId": null, "cloid": "0xdd0cd482496f45f79c5ffbe7c27e1511" }, { "coin": "ETH", "px": "2658.9", "sz": "1.0", "side": "A", "time": 1790608928951, "startPosition": "-776.0", "dir": "Open Short", "closedPnl": "0.0", "hash": "0xd8c5bd7a...25ae9e33", "oid": 559115788953, "crossed": true, "fee": "1.196505", "builderFee": "0.26589", "tid": 825882878864874, "feeToken": "USDC", "twapId": null } ]

두 체결은 거래의 tid, 가격, 수량, 시간을 공유합니다. 나머지는 모두 계정별 값입니다.

  • oid. 이 체결을 만든 주문입니다. 매수자와 매도자는 각자 다른 값을 가집니다.
  • crossed. 테이커는 true, 메이커(오더북에 대기 중이던 주문)는 false입니다.
  • fee. 이 계정이 지불한 수수료입니다. 위 매수자의 체결처럼 음수 값은 메이커 리베이트입니다. builderFee가 있다면 빌더(주문을 라우팅한 프론트엔드나 앱)에게 지급된 부분이며, 이미 fee에 포함되어 있습니다.
  • startPosition, dir, closedPnl. 체결 전 포지션 크기, Open Long이나 Close Short 같은 표시용 라벨, 그리고 이 체결로 실현된 PnL입니다. 이 값들만 있으면 체결만으로 포지션 내역을 재구성할 수 있습니다.
  • liquidation. 일반 체결에서는 null입니다. 청산의 경우 청산된 계정, 마크 가격, 그리고 청산이 마켓을 통해 이루어졌는지 백스톱을 통해 이루어졌는지를 나타냅니다.
  • twapId. 이 체결을 만든 TWAP 주문으로, 해당하는 경우에만 존재합니다.

수수료, 리베이트, 실현 PnL, 청산 세부 정보는 체결에만 존재하므로, 원장이나 세금 보고서는 모두 체결을 기반으로 만들어야 합니다.

주문, 거래, 체결은 어떻게 조인되는가?

거의 모든 조인은 두 개의 키로 이루어집니다.

조인
키
카디널리티
거래 → 체결
tid(coin, time과 함께)
거래 1건당 체결 정확히 2건
체결 → 주문
oid
주문 1건당 체결 0건 이상
주문 → 클라이언트 요청
cloid
설정한 경우 일대일
체결 또는 거래 → 트랜잭션
hash
다대일, TWAP 슬라이스는 hash가 모두 0

기반으로 삼아야 할 것은 처음 두 행입니다. 저희는 trades에서 거래 하나를 가져온 뒤 users 배열에 있는 두 주소의 체결을 조회하는 방식으로, 실제 데이터에서 거래-체결 조인을 확인했습니다. 각 주소에는 해당 거래의 tid를 가진 체결이 정확히 하나씩 있었고, 하나는 crossed: true, 다른 하나는 crossed: false였습니다.

주문의 잔여 수량은 체결-주문 조인에서 바로 도출됩니다.

text
Copied
remaining = origSz - sum(fill.sz for every fill where fill.oid == order.oid)

이 공식은 모든 주문에 대해 성립하며, 마지막으로 받은 주문 업데이트의 sz보다 이 결과를 신뢰해야 합니다.

체결로 주문 상태를 어떻게 대사하는가?

아래 스크립트는 한 계정의 주문 업데이트와 체결을 구독하고, 각 주문의 체결 수량을 체결로부터 추적하며, 주문이 최종 상태에 도달했을 때 거래소가 보고하는 sz와 그 계산 결과를 대조합니다. WebSocket을 기본 지원하는 최신 Node 릴리스에서 실행되며 의존성이 필요 없습니다.

javascript
Copied
// Tracks one account's orders by joining order-status events with fills. // Usage: node reconcile.mjs 0xYourAddress const WS_URL = process.env.HL_WS_URL ?? "wss://api.hyperliquid.xyz/ws"; const user = process.argv[2]; if (!/^0x[0-9a-fA-F]{40}$/.test(user ?? "")) throw new Error("pass a 0x address"); // Sizes arrive as decimal strings. Sum them as scaled integers so partial fills add up exactly. const SCALE = 10; const units = (s) => { const [i, f = ""] = s.split("."); return BigInt(i + f.padEnd(SCALE, "0").slice(0, SCALE)); }; const fmt = (u) => (Number(u) / 10 ** SCALE).toString(); const orders = new Map(); // oid -> { coin, origSz, filled, status, reported } const seenFills = new Set(); // coin|time|tid, so a fill delivered twice is counted once const fillKey = (f) => `${f.coin}|${f.time}|${f.tid}`; const order = (oid) => { if (!orders.has(oid)) orders.set(oid, { filled: 0n, status: "unknown" }); return orders.get(oid); }; // Runs whenever a terminal order learns something new, so either stream can arrive first. function check(oid, o) { if (o.reported === undefined) return; // not terminal yet const remaining = o.origSz - o.filled; if (remaining === o.reported && o.filled === 0n) return; // plain cancel or reject const result = remaining === o.reported ? "ok" : remaining > o.reported ? `waiting for fills (${fmt(remaining - o.reported)} outstanding)` : `MISMATCH (fills say ${fmt(remaining)})`; console.log(`${oid} ${o.coin} ${o.status}: filled ${fmt(o.filled)} of ${fmt(o.origSz)}, sz=${fmt(o.reported)} ${result}`); } function onOrderUpdate(u) { const o = order(u.order.oid); Object.assign(o, { coin: u.order.coin, origSz: units(u.order.origSz), status: u.status }); if (u.status === "open") return; o.reported = units(u.order.sz); check(u.order.oid, o); } function onFill(f, quiet = false) { const key = fillKey(f); if (seenFills.has(key)) return; seenFills.add(key); const o = order(f.oid); o.filled += units(f.sz); if (!quiet) { const role = f.crossed ? "taker" : "maker"; console.log(`${f.oid} ${f.coin} fill tid=${f.tid} ${f.side} ${f.sz}@${f.px} ${role} fee=${f.fee}${f.liquidation ? " LIQUIDATION" : ""}`); } check(f.oid, o); } const ws = new WebSocket(WS_URL); ws.onopen = () => { for (const type of ["orderUpdates", "userFills"]) { ws.send(JSON.stringify({ method: "subscribe", subscription: { type, user } })); } }; ws.onmessage = ({ data }) => { const msg = JSON.parse(data); if (msg.channel === "orderUpdates") msg.data.forEach(onOrderUpdate); if (msg.channel !== "userFills") return; // The first message is a snapshot of recent fills. Count it, so orders already partly // filled at startup add up, but don't print it. The dedupe set absorbs it on reconnect. const { fills, isSnapshot } = msg.data; fills.forEach((f) => onFill(f, isSnapshot)); if (isSnapshot) console.log(`loaded ${fills.length} fills from the snapshot`); }; ws.onclose = () => console.log("closed; reconnect and backfill from your last stored fill time");

활성 주소라면 어떤 주소든 대상으로 실행할 수 있습니다. 예를 들어 최근 거래의 users 배열에서 가져온 주소를 사용하면 됩니다. 거래가 많은 계정을 대상으로 45초 동안 실행한 출력은 다음과 같았습니다.

text
Copied
loaded 30 fills from the snapshot 580847595557 HYPE fill tid=524471650157202 B [email protected] taker fee=1.800529 580847595557 HYPE fill tid=1042881790178215 B [email protected] taker fee=0.71124 580847595557 HYPE filled: filled 214.47 of 221.99, sz=7.52 ok 580847576684 ZEC fill tid=38729269326008 B [email protected] maker fee=-0.0005 580847576684 ZEC canceled: filled 0.02 of 2.47, sz=2.45 ok

첫 줄은 구독이 시작될 때 전달되는 스냅샷입니다. 다음 세 줄은 하나의 Ioc 주문이 대기 주문 두 개를 소진해 두 건의 체결을 만들고, 7.52 HYPE가 미체결된 채 filled로 끝난 경우입니다. 마지막 두 줄은 오더북에 대기하던 Alo 주문이 메이커로서 0.02 ZEC를 체결한 뒤, 나머지가 아직 오더북에 남아 있는 상태에서 취소된 경우입니다. 이 실행에서 체결이 있었던 주문 중 최종 상태에 도달한 115건 모두에서, 체결로부터 도출한 잔여 수량이 거래소가 보고한 sz와 일치했습니다.

스크립트에서 중요한 세부 사항이 세 가지 있습니다. 수량은 문자열이며, 이를 JavaScript 부동소수점으로 합산하면 부분 체결이 많은 장기 주문에서 반올림 오차가 누적되므로, 스크립트는 스케일된 정수로 합산합니다. 또한 대조는 두 핸들러 모두에서 실행됩니다. 최종 상태가 도착하면 보고된 sz를 저장하고, 그 뒤에 도착하는 체결마다 비교를 다시 실행하므로, 마지막 체결이 filled 상태보다 늦게 도착한 주문은 잘못된 불일치 판정 대신 waiting for fills를 거쳐 ok로 표시됩니다. 마지막으로, 체결은 상태에 반영되기 전에 중복 제거되므로, 재연결 후의 스냅샷이나 실시간 스트림과 겹치는 백필처럼 같은 체결이 두 번 도착해도 한 번만 집계됩니다.

Hyperliquid의 WebSocket 문서는 tid를 50비트 해시라고 설명하고, 블록 시간, coin, tid의 조합을 전역적으로 고유한 거래 ID로 규정하므로, 스크립트는 coin, time, tid를 체결의 키로 사용합니다. 거래와 그 두 체결은 이 세 값을 모두 공유합니다. 이 키는 한 계정 안에서 고유합니다. 한 프로세스에서 여러 계정을 추적한다면, 거래의 양쪽이 나머지 값을 모두 공유하므로 키에 user를 추가하세요.

프로덕션에서는 무엇이 깨지는가?

대부분의 대사 버그는 다음과 같은 경우에서 발생합니다.

  • 중복 전달. 다시 구독하면 네이티브 userFills 스트림은 최근 체결의 스냅샷(isSnapshot: true)으로 시작하고, 백필은 실시간 스트림이 이미 전달한 내용과 겹칩니다. 체결은 user, coin, time, tid의 조합으로, 주문 업데이트는 oid, status, statusTimestamp의 조합으로 중복 제거하세요.
  • 스트림 간 순서. 주문 업데이트와 체결은 별도의 채널로 도착합니다. 체결이 해당 주문의 filled 상태보다 먼저 도착한다고 가정하지 말고, 그 반대도 가정하지 마세요. 스크립트처럼 상태를 oid로 키잉하고, 어느 이벤트든 레코드를 생성할 수 있게 하며, 늦게 도착한 체결에 대해 대조를 다시 실행하면 이 의존성이 사라집니다.
  • 연결 끊김. WebSocket 구독은 연결되어 있는 동안 발생한 것만 전달하므로, 다운타임이 생기면 반드시 백필이 필요합니다. 마지막으로 처리한 체결의 시간을 저장해 두고, 아래와 같이 그 시점부터 체결을 조회하세요.
  • TWAP 슬라이스 체결. TWAP 슬라이스는 hash가 0인 상태로 실행됩니다. 공개 Hyperliquid API에서 저희가 추적한 슬라이스 체결은 userFillsByTime이 아니라 userTwapSliceFills에 나타났으므로, userFillsByTime만 읽는 백필은 이를 놓칠 수 있습니다.
  • 알 수 없는 상태. 새로운 거부 및 취소 사유는 계속 추가됩니다. 알 수 없는 값은 크래시 없이 처리하고, triggerCondition은 표시용 문자열로 취급하세요. 기계가 읽을 수 있는 트리거 가격은 triggerPx입니다.
  • 마켓 식별자. 코인 문자열은 마켓 유형을 인코딩합니다. 마켓, 자산, DEX 문서에 설명된 대로, BTC는 무기한 선물이고, 현물 마켓은 @index 형식의 문자열(예: @107)을, 아웃컴 마켓은 #N을, 서드파티가 배포한 HIP-3 마켓은 dex:name을 사용합니다. 코인 문자열은 대소문자를 구분하므로 정확히 일치하는지 비교하고, 절대 소문자로 변환하지 마세요.
  • 너무 이른 체크포인트 갱신. 마지막 체결 시간은 해당 체결이 스토리지에 기록된 뒤에만 저장하세요. 먼저 갱신하면 두 단계 사이에 크래시가 발생했을 때 체결 하나가 조용히 누락됩니다.

특정 시간 범위의 체결을 백필하는 데는 짧은 루프면 충분합니다. Hyperliquid의 info 엔드포인트 문서에 따르면 userFillsByTime은 체결을 오래된 순으로, 응답당 최대 2,000건까지 반환합니다. 따라서 루프는 지금까지 본 가장 최근 시간에서 다시 시작하고, 겹치는 부분은 같은 중복 제거 키로 흡수합니다.

javascript
Copied
// Pulls every fill for an account between two times, for use after a stream gap. // Usage: node backfill.mjs 0xYourAddress <startMs> [endMs] const INFO_URL = process.env.HL_INFO_URL ?? "https://api.hyperliquid.xyz/info"; const [user, start, end = Date.now()] = process.argv.slice(2); async function fillsBetween(user, startTime, endTime) { const byKey = new Map(); let from = Number(startTime); while (true) { const res = await fetch(INFO_URL, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ type: "userFillsByTime", user, startTime: from, endTime: Number(endTime) }), }); const page = await res.json(); const before = byKey.size; for (const f of page) byKey.set(`${f.coin}|${f.time}|${f.tid}`, f); // Pages are capped. Restart at the newest time seen; the dedupe key absorbs the overlap. if (page.length === 0 || byKey.size === before) break; from = Math.max(...page.map((f) => f.time)); } return [...byKey.values()].sort((a, b) => a.time - b.time); } const fills = await fillsBetween(user, start, end); console.log(`${fills.length} fills`);

같은 계정을 대상으로 30분 구간을 조회하자 4개 페이지에 걸쳐 6,049건의 체결이 반환되었습니다. 결과를 스트림이 사용하는 것과 같은 onFill 핸들러에 넘기면, 중복 제거 집합이 백필과 실시간 스트림 사이의 겹치는 부분이 이중으로 집계되지 않도록 막아 줍니다.

같은 문서에 따르면 userFillsByTime으로는 가장 최근 10,000건의 체결만 조회할 수 있습니다. 위의 속도라면 1시간이 채 안 되는 분량의 내역이므로, 이만큼 활발한 계정에서 그보다 긴 장애가 생기면 공개 엔드포인트가 반환할 수 있는 범위를 벗어납니다. 연결이 끊긴 컨슈머를 이 구간 안에서 충분히 여유 있게 감지할 수 있도록 알림을 설정하세요.

Alchemy의 HyperCore 스트리밍은 이를 어떻게 바꾸는가?

Alchemy의 HyperCore 스트리밍은 네이티브 구독 엔벨로프를 그대로 사용하므로, 위의 페이로드와 조인 로직은 동일하게 유지됩니다. 차이는 각 프레임이 출처 블록에 대해 알려 주는 정보와, 구독 하나가 다룰 수 있는 범위에 있습니다.

모든 데이터 프레임은 네이티브 페이로드와 함께 subscriptionId, blockHeight, blockTime 등의 최상위 메타데이터를 담고 있습니다. 주문 업데이트와 체결은 여전히 별도의 채널로 도착하지만, 각 프레임이 출처 블록을 명시하므로 두 스트림을 맞춰 볼 때 공통 기준점이 생깁니다.

구독은 배열도 받습니다. 네이티브 구독은 단일 user 또는 coin만 받지만, 저희 구독은 users, coins, builders를 받으므로 구독 하나로 여러 계정을 한꺼번에 다룰 수 있습니다. 모든 체결 및 주문 레코드에는 user가 담겨 있으므로, 위에서 설명한 다중 계정 중복 제거 키가 예외적인 경우가 아니라 기본 경우가 됩니다.

넓은 피드에서 직접 걸러낼 필요가 없도록 몇 가지 전용 스트림이 제공됩니다.

  • liquidationFills. 청산이 포함된 체결만 마켓별로 필터링해 제공합니다.
  • builderFills 및 builderOrderUpdates. 빌더 주소에 귀속된 체결과 주문 업데이트로, 주문을 라우팅하면서 자체 주문 흐름과 수수료를 추적해야 하는 앱을 위한 스트림입니다.
  • allFills. 선택한 마켓에 있는 모든 계정의 체결로, 더 간소한 거래 레코드가 아니라 전체 체결 스키마를 제공합니다.

저희 엔드포인트에서 대사 스크립트를 실행하려면, HL_WS_URL을 얼리 액세스와 함께 받은 WebSocket URL로 지정하고, HyperCore 연결 수명 주기 문서에 설명된 대로 인증한 다음, orderUpdates 대신 userOrderUpdates를 구독하세요. 저희 주문 업데이트 프레임은 상태 레코드를 orders 배열로 감싸므로, msg.data가 아니라 msg.data.orders에서 읽어야 합니다. 과거 데이터를 위해 저희 HyperCore REST API에 커서 기반 페이지네이션을 지원하는 userFillsByTime과 historicalOrders가 추가될 예정입니다. 두 메서드 모두 지갑 트레이딩 내역 조회 가이드에 문서화되어 있지만 아직 호출할 수는 없으므로, 위의 백필 스크립트는 그동안 공개 Hyperliquid 엔드포인트를 사용합니다.

HyperCore 스트리밍에는 어떻게 액세스하는가?

HyperCore 스트리밍은 저희가 6월에 발표한 HyperCore 작업의 일환으로 현재 얼리 액세스 단계입니다. 저희가 운영하는 Hyperliquid 노드에서 스트리밍하므로 hl-node를 직접 운영할 필요가 없으며, 이미 Alchemy에서 빌드하고 있다면 지금 사용 중인 API 키에서 바로 활성화해 드립니다. 먼저 HyperCore 데이터 API 개요에서 스트림과 REST 메서드를 확인한 다음, HyperCore 얼리 액세스를 신청하여 연결 정보를 받고 저희 팀과 직접 협업하세요.

스택의 나머지 부분에 쓸 스트리밍 전송 방식을 고르고 있다면, webhooks, WebSockets, gRPC 비교 글에서 각 방식의 트레이드오프를 다룹니다. Hyperliquid의 HyperEVM 쪽은 Hyperliquid RPC 가이드를 참고하세요.

Background gradient

블록체인 매직을 만드세요

Alchemy는 가장 강력한 Web3 개발자 제품 및 도구를 리소스, 커뮤니티, 그리고 전설적인 지원과 결합합니다.