Ủy quyền Agent
Hỗ trợ ký đa khóa cho nhà tạo lập thị trường.
Tổng quan
Ủy quyền agent cho phép một khóa ký chuyên dụng (agent) đặt và hủy lệnh thay mặt cho một ví giao dịch. Tính năng này hữu ích cho:
- Bảo mật: Giữ khóa ví giao dịch trong kho lạnh, dùng khóa nóng để ký
- Vận hành: Nhiều thành viên trong nhóm có thể ký bằng các khóa khác nhau
- Tự động hóa: Các hệ thống tự động có thể ký bằng khóa chuyên dụng
Hai mô hình ủy quyền
Hypercall có hai hệ thống ủy quyền riêng biệt tùy theo sản phẩm:
| Sản phẩm | Loại ủy quyền | Nơi lưu trữ | Cách thiết lập |
|---|---|---|---|
| Quyền chọn (REST API) | Ủy quyền agent | Trạng thái engine của Hypercall | POST /approve-agent |
| Perp | Ví API | On-chain (hợp đồng Account của bạn) | Directive hc_update_api_wallet |
Đây là hai hệ thống độc lập. Việc phê duyệt một agent để giao dịch quyền chọn không cấp quyền cho agent đó giao dịch perp, và ngược lại.
Quyền chọn: Ủy quyền Agent (Off-Chain)
Agent ký các thông điệp EIP-712 PlaceOrder và CancelOrder thay mặt cho một ví giao dịch. API kiểm tra agent dựa trên trạng thái ủy quyền của engine trước khi lệnh đến được engine.
Perp: Ví API (On-Chain)
Ví API ký các lệnh perp và lệnh hủy trong domain EIP-712 HypercallApiSign. Hypercall kiểm tra người ký dựa trên hợp đồng Account của bạn (isApiWalletActive()) trước khi chấp nhận lệnh. Trên tuyến TEE (mặc định của ứng dụng, và tùy chọn bật cho các client API), một enclave bảo mật nắm giữ một khóa giao dịch Hyperliquid riêng cho Account của bạn sẽ ký và gửi lệnh gốc; trên tuyến hợp đồng thông minh, một cài đặt nâng cao trong ứng dụng, lệnh đi qua hợp đồng Account của bạn. Xem Ký EIP-712 để tham khảo về cách ký và Perp để biết luồng xử lý.
Để thêm hoặc xóa một ví API, hãy gửi directive hc_update_api_wallet được ký bởi ví quản lý (manager) của tài khoản.
Mô hình này phản ánh mô hình ví API của Hyperliquid. Hyperliquid gọi chúng là ví API, còn gọi là ví agent, trong tài liệu Nonces and API wallets, và mô tả approveAgent trong tài liệu Exchange endpoint.
Chống phát lại Nonce
Việc theo dõi nonce tuân theo mô hình nonce của Hyperliquid. Tất cả các hành động được ký (lệnh, phê duyệt/thu hồi agent, bắt tay QP) dùng chung một không gian nonce theo từng người ký. Engine lưu 100 nonce cao nhất cho mỗi địa chỉ người ký. Một nonce mới được chấp nhận nếu:
!stored_set.contains(nonce): nonce không bị trùng lặpnonce > min(stored_set)khi tập đã chứa 100 phần tử: nonce lớn hơn nonce nhỏ nhất đang được lưunoncenằm trong khoảng (T - 2 ngày, T + 1 ngày) so với dấu thời gian của máy chủ
Nonce không theo thứ tự vẫn được chấp nhận (ví dụ: nonce 105 rồi đến 102 đều hợp lệ nếu cả hai đều lớn hơn giá trị nhỏ nhất của tập). Tập được giới hạn ở 100 phần tử, vì vậy các phần tử cũ nhất sẽ bị loại bỏ khi phần tử mới được thêm vào. Điều này ngăn tài khoản bị khóa vĩnh viễn chỉ vì một nonce quá lớn.
Người ký nonce là địa chỉ đã ký thông điệp EIP-712: ví API đối với lệnh, người ký được khôi phục đối với ủy quyền agent, ví QP đối với bắt tay. Client nên dùng Date.now() (epoch tính bằng mili giây) làm giá trị khởi tạo nonce và tăng dần đơn điệu.
Ủy quyền Agent cho Quyền chọn
Ký trực tiếp
Nếu signer == wallet, lệnh luôn được ủy quyền (tự ký).
Ký bằng Agent
Nếu signer != wallet, người ký phải là một agent đã được ủy quyền:
- Agent phải có mặt trong trạng thái ủy quyền do engine sở hữu
- Ủy quyền không được hết hạn
- Snapshot của engine và nhật ký (journal) của engine là các nguồn bền vững để khôi phục khi khởi động lại
Phê duyệt Agent
Endpoint: POST /approve-agent
Yêu cầu: ApproveAgentRequest
{
"agent": "0x...",
"nonce": 1,
"signature": "0x..."
}
Ký:
- Chủ sở hữu ví ký thông điệp
ApproveAgent - Ví được suy ra từ chữ ký được khôi phục
- Agent là trường
agenttrong yêu cầu
Struct EIP-712:
struct ApproveAgent {
address agent;
uint64 nonce;
}
Phản hồi: ApproveAgentResponse
{
"success": true,
"error": null
}
Ghi chú:
- Ủy quyền agent là trạng thái engine được ghi vào journal và vẫn tồn tại sau khi khởi động lại
- Các phê duyệt được thực hiện qua endpoint này không hết hạn
Thu hồi Agent
Endpoint: DELETE /revoke-agent
Yêu cầu: RevokeAgentRequest
{
"agent": "0x...",
"nonce": 2,
"signature": "0x..."
}
Ký:
- Chủ sở hữu ví ký thông điệp
RevokeAgent - Ví được suy ra từ chữ ký được khôi phục
Struct EIP-712:
struct RevokeAgent {
address agent;
uint64 nonce;
}
Phản hồi: RevokeAgentResponse
Ghi chú:
- Áp dụng một lệnh
RevokeAgentđược ghi vào journal lên trạng thái ủy quyền do engine sở hữu - Các bước kiểm tra ủy quyền của API giao dịch đọc trạng thái backend và thực thi việc thu hồi đối với các yêu cầu giao dịch. Việc đăng bài trên Trollbox có thể lưu cache ủy quyền agent hợp lệ lâu hơn, vì vậy một agent vừa bị thu hồi vẫn có thể đăng bài cho đến khi cache đó hết hạn hoặc việc vô hiệu hóa theo cơ chế best-effort đến được vị trí edge liên quan. Cache này không cấp quyền cho các thao tác thay đổi qua API giao dịch.
- Agent không thể ký thay cho ví sau khi bị thu hồi
Thu hồi tất cả Agent
Endpoint: DELETE /revoke-all-agents
Yêu cầu: { "nonce": 3, "signature": "0x..." }, được ký bởi chủ sở hữu ví trên RevokeAllAgents(uint64 nonce). Xóa mọi agent của ví được khôi phục.
Lấy danh sách Agent được ủy quyền
Endpoint: GET /authorized-agents?wallet=...
Tham số truy vấn:
wallet(bắt buộc)
Phản hồi:
{
"agents": [
"0x...",
"0x..."
]
}
Ghi chú:
- Chỉ trả về các agent đang hoạt động và chưa hết hạn
Sử dụng Agent
Ký lệnh bằng Agent
Sau khi agent được phê duyệt:
- Ký lệnh bằng ví agent: Dùng ví agent để ký các thông điệp
PlaceOrder/CancelOrder - Đặt trường wallet: Đặt trường
walletthành địa chỉ ví giao dịch (không phải địa chỉ agent) - Xác minh ở middleware: Middleware xác minh agent đã được ủy quyền cho ví đó
Ví dụ:
// Agent wallet signs the order
const agentSigner = new ethers.Wallet(agentPrivateKey);
const message = {
wallet: "0x...", // Trading wallet (not agent)
symbol: "BTC-20250131-100000-C",
side: "Buy",
size: "0.1",
price: "100.0",
tif: "gtc",
clientId: "mm-1",
nonce: 1
};
// Sign with agent wallet
const signature = await agentSigner._signTypedData(domain, types, message);
// Send request. The REST body uses snake_case `client_id`.
const { clientId, ...rest } = message;
const response = await fetch('/order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...rest,
client_id: clientId,
signature
})
});
Lệnh hàng loạt với Agent
Các endpoint hàng loạt xác minh ủy quyền agent cho từng mục:
- Mỗi lệnh trong
POST /bulk_ordercó thể được ký bởi một agent khác nhau - Ủy quyền agent được kiểm tra cho từng mục
- Nếu bất kỳ mục nào không vượt qua kiểm tra ủy quyền agent, mục đó trả về lỗi trong
BulkOrderResult
Kiểm tra ủy quyền
Middleware (Lệnh đơn)
Endpoint:
POST /orderDELETE /orderDELETE /order_cloid
Kiểm tra: signature_and_agent_middleware xác minh:
- Khôi phục chữ ký thành công
- Người ký được ủy quyền (signer == wallet HOẶC agent đã được ủy quyền)
Handler (Lệnh hàng loạt)
Endpoint:
POST /bulk_orderDELETE /bulk_orderDELETE /bulk_order_cloid
Kiểm tra: Xác minh từng mục trong handler:
- Khôi phục chữ ký cho từng mục
- Kiểm tra ủy quyền agent cho từng mục
Lưu trữ ủy quyền
Ủy quyền agent là trạng thái do engine sở hữu. Các lệnh ApproveAgent và RevokeAgent được ghi vào journal, được khôi phục thông qua việc phát lại engine, và được cung cấp qua snapshot đọc để API kiểm tra.
Logic ủy quyền
Ủy quyền người ký sử dụng logic OR tường minh:
- Ký trực tiếp:
signer == wallet. - Ký bằng agent: snapshot của engine chứa một bản ghi ủy quyền cho
wallet_address == <wallet>vàagent_address == <signer>, vàexpires_atkhông có hoặc nằm trong tương lai.
Hết hạn
Engine hỗ trợ trường expires_at cho một ủy quyền và coi agent đã hết hạn
là chưa được ủy quyền. POST /approve-agent không đặt trường này, vì vậy các agent
được phê duyệt qua API vẫn hoạt động cho đến khi bị thu hồi.
Lưu ý bảo mật
- Bảo mật khóa agent: Bảo vệ khóa riêng của agent (dùng ví phần cứng hoặc hệ thống quản lý khóa an toàn)
- Kiểm tra định kỳ: Thường xuyên rà soát các agent được ủy quyền qua
GET /authorized-agents - Thu hồi agent không dùng: Thu hồi các agent không còn cần thiết
Thực hành tốt nhất
- Dùng agent cho tự động hóa: Giữ khóa ví giao dịch trong kho lạnh, dùng agent cho các hệ thống tự động
- Giới hạn phạm vi agent: Chỉ phê duyệt những agent cần quyền truy cập
- Giám sát việc sử dụng agent: Theo dõi agent nào đang đặt lệnh
- Thu hồi kịp thời: Thu hồi agent ngay lập tức khi không còn cần thiết
Sự cố thường gặp
"Signer 0x... is not authorized to act for wallet 0x..."
Nguyên nhân: Agent chưa được phê duyệt hoặc ủy quyền đã hết hạn/bị thu hồi.
Giải pháp: Phê duyệt agent qua POST /approve-agent hoặc ký trực tiếp bằng ví.
Ủy quyền Agent không hoạt động
Nguyên nhân:
- Agent không có mặt trong trạng thái ủy quyền do engine sở hữu
- Ủy quyền đã bị thu hồi
- Ủy quyền đã hết hạn
Giải pháp: Kiểm tra trạng thái agent qua GET /authorized-agents?wallet=....