Kimlik Doğrulama ve İmzalama
Yazma işlemleri için EIP-712 imza gereksinimleri.
Üretim ortamı için chain ID 999 kullanın. Testnet, Hypercall daha fazla testnet HYPE edinene kadar geçici olarak devre dışıdır.
Genel Bakış
Tüm yazma işlemleri EIP-712 tipli veri imzası gerektirir. İmzalayan taraf şunlardan biri olmalıdır:
- Cüzdan adresinin kendisi (doğrudan imzalama), VEYA
- Cüzdan için yetkilendirilmiş bir ajan (bkz. Ajan yetkilendirmesi)
EIP-712 Domain
Domain ayırıcı:
{
"name": "Hypercall",
"version": "1",
"chainId": 999,
"verifyingContract": "0x0000000000000000000000000000000000000000"
}
Chain ID: 999 (üretim)
Mesaj Türleri
PlaceOrder
Açık route içeren struct:
struct PlaceOrder {
address wallet;
string symbol;
string side;
string size;
string price;
string tif;
string route;
string clientId;
uint64 nonce;
}
Route belirtilmediğinde kullanılan struct:
struct PlaceOrder {
address wallet;
string symbol;
string side;
string size;
string price;
string tif;
string clientId;
uint64 nonce;
}
Alan gereksinimleri:
wallet: Cüzdan adresi (0x önekli hex string)symbol: Opsiyon sembolü (ör."BTC-20250131-100000-C")side:"Buy"veya"Sell"(birebir string eşleşmesi gerekir)size: String olarak büyüklük (ör."0.1") - JSON'da gönderilen değerle BİREBİR eşleşmelidirprice: String olarak fiyat (ör."100.0") - JSON'da gönderilen değerle BİREBİR eşleşmelidirtif: Time-in-force:"gtc","ioc"veya"fok"(birebir string eşleşmesi gerekir)route: İsteğe bağlı emir yönlendirmesi:"best_execution"veya"book_only"(mevcutsa birebir string eşleşmesi gerekir).POST /bulk_orderyalnızca"book_only"kabul eder."rfq_only"imzalanan sözlüğün bir parçasıdır ancak şu anda tüm emir endpoint'leri bunu reddeder; RFQ ile işlem için RFQ endpoint'lerini kullanın.clientId: İstemci tarafından verilen emir ID'si (string, boş""olabilir)nonce: Milisaniye zaman damgası nonce'u (uint64), imzalayan başına benzersiz. Bkz. Nonce Yönetimi
Kritik: price ve size, hem imzalanan mesajda hem de JSON istek gövdesinde string OLMALIDIR. String biçimlendirmesi birebir eşleşmelidir.
Varsayılan route: route gönderin. Bu alanı içermeyen bir emir yine kabul edilir ve best_execution olarak yönlendirilir, ancak POST /order yanıtında Deprecation, Sunset ve Warning başlıkları döner ve yayımlanan sunset tarihi (4 Temmuz 2026) geçmiştir. Route içermeyen biçim, ek bir geçiş süresi tanınmadan kaldırılabilir. JSON'da route alanını çıkarırsanız, tipli veriden de çıkarın.
PlaceOrderReduceOnly
Yalnızca pozisyon azaltan bir emir (JSON gövdesinde "reduce_only": true) ayrı bir struct imzalar. Açık bir route gerektirir.
struct PlaceOrderReduceOnly {
address wallet;
string symbol;
string side;
string size;
string price;
string tif;
string route;
string clientId;
bool reduceOnly;
uint64 nonce;
}
reduceOnly değeri true olmalı ve istek gövdesiyle eşleşmelidir. İmzalı bir route içermeyen reduce-only emir missing_field hatasıyla reddedilir.
ReplaceOrder
PUT /order ve PUT /bulk_order içindeki her giriş bir ReplaceOrder imzalar. Bu struct'ta route alanı yoktur; JSON gövdesindeki route anahtarı yok sayılır.
struct ReplaceOrder {
address wallet;
string orderId;
string symbol;
string side;
string size;
string price;
string tif;
string clientId;
uint64 nonce;
}
orderId, değiştirilen emrin ondalık string karşılığıdır. Reduce-only bir değiştirme ("reduce_only": true), clientId ile nonce arasına bool reduceOnly ekleyen ReplaceOrderReduceOnly struct'ını imzalar. TypeScript SDK her iki tip haritasını da dışa aktarır.
CancelOrder
Struct:
struct CancelOrder {
address wallet;
string orderId;
uint64 nonce;
}
Alan gereksinimleri:
wallet: Cüzdan adresiorderId: String olarak emir ID'si (ör."123")nonce: Benzersiz nonce
CancelOrderByClientId
Struct:
struct CancelOrderByClientId {
address wallet;
string clientId;
uint64 nonce;
}
Alan gereksinimleri:
wallet: Cüzdan adresiclientId: İstemci emir ID'si (string)nonce: Benzersiz nonce
ApproveAgent
Struct:
struct ApproveAgent {
address agent;
uint64 nonce;
}
Alan gereksinimleri:
agent: Yetkilendirilecek ajan cüzdan adresinonce: Benzersiz nonce
Not: Ajanı yetkilendiren cüzdan, geri elde edilen imzadan türetilir.
RevokeAgent
Struct:
struct RevokeAgent {
address agent;
uint64 nonce;
}
Alan gereksinimleri:
agent: Yetkisi kaldırılacak ajan cüzdan adresinonce: Benzersiz nonce
RevokeAllAgents
DELETE /revoke-all-agents, imzalayan cüzdana ait tüm ajanları kaldırır.
struct RevokeAllAgents {
uint64 nonce;
}
Risk simülasyonu
POST /risk/simulate/portfolio ve POST /risk/simulate/orders, herkese açık ve
salt okunur engine-authority istekleridir. İmza, kimlik doğrulama veya nonce
gerektirmezler. wallet alanı, değerlendirilecek hesap snapshot'ını seçer.
Portföy isteği örneği:
curl -X POST https://api.hypercall.xyz/risk/simulate/portfolio \
-H 'Content-Type: application/json' \
-d '{
"wallet": "0x1111111111111111111111111111111111111111",
"add_positions": true,
"positions": [
{"symbol": "BTC-20261231-100000-C", "quantity": "1.25"}
]
}'
Atomik emir isteği örneği:
curl -X POST https://api.hypercall.xyz/risk/simulate/orders \
-H 'Content-Type: application/json' \
-d '{
"wallet": "0x1111111111111111111111111111111111111111",
"execution_mode": "atomic",
"hypothetical_open_orders": [
{"symbol": "BTC-PERP", "side": "Buy", "size": "0.1", "price": "100000", "reduce_only": false}
],
"orders": [
{"symbol": "BTC-20261231-100000-C", "side": "Buy", "size": "1", "price": "4200", "reduce_only": false},
{"symbol": "BTC-20261231-120000-C", "side": "Sell", "size": "1", "price": "1800", "reduce_only": false}
]
}'
hypothetical_open_orders isteğe bağlıdır. Girişleri, defterde bekleyen GTC
emirler olarak ele alınır ve orders öncesinde dizi sırasıyla tek tek kabul
edilir. Yalnızca bu istek için, hesabın yetkili canlı açık emirleri ve aktif
rezervasyonlarıyla birlikte değerlendirilirler. Engine durumu değiştirilmez.
Başarılı bir simülasyonda simulated ve delta, varsayımsal dizinin tamamını
ve önerilen bekleyen emri ya da atomik paketi içerir. İki emir dizisi toplamda
en fazla 50 giriş içerebilir.
Simülasyon yanıtları birer snapshot'tır, gerçekleşme garantisi değildir. Yönlendirme, RPI erişilebilirliği, eşleştirme, nonce kabulü ve gelecekteki işlem durdurma durumu simüle edilmez. Engine durumu ilerledikçe sonraki gerçek bir emir farklı sonuçlanabilir.
İmzalama Süreci
Adım 1: Mesajı Oluşturun
Açık route içeren PlaceOrder örneği:
const message = {
wallet: "0x1111111111111111111111111111111111111111",
symbol: "BTC-20250131-100000-C",
side: "Buy",
size: "0.1", // MUST be string
price: "100.0", // MUST be string
tif: "gtc",
route: "best_execution",
clientId: "mm-1",
nonce: Date.now() // current ms epoch; send this exact value in the body
};
Adım 2: Domain'i Tanımlayın
const domain = {
name: "Hypercall",
version: "1",
chainId: 999,
verifyingContract: "0x0000000000000000000000000000000000000000"
};
Adım 3: Tipli Veriyi İmzalayın
ethers.js v6 kullanarak (v5'te metot adı _signTypedData'dır):
const signature = await signer.signTypedData(domain, {
PlaceOrder: [
{ name: "wallet", type: "address" },
{ name: "symbol", type: "string" },
{ name: "side", type: "string" },
{ name: "size", type: "string" },
{ name: "price", type: "string" },
{ name: "tif", type: "string" },
{ name: "route", type: "string" },
{ name: "clientId", type: "string" },
{ name: "nonce", type: "uint64" }
]
}, message);
Adım 4: İsteği Gönderin
Kritik: JSON istek gövdesi, price ve size için birebir aynı string değerleri kullanmalıdır:
const body = {
wallet: message.wallet,
symbol: message.symbol,
price: message.price, // same string as signed
size: message.size, // same string as signed
side: message.side,
tif: message.tif,
route: message.route,
client_id: message.clientId,
nonce: message.nonce, // same value as signed
signature
};
Nonce Yönetimi
Gereksinimler:
- Nonce'lar, milisaniye cinsinden sunucu saatinin kesinlikle iki gün öncesi ile bir gün sonrası arasında olmalıdır; bu nedenle milisaniye cinsinden güncel Unix zamanını kullanın.
1veya123gibi küçük sayaçlar reddedilir. - Nonce'lar imzalama anahtarı başına takip edilir. Emirler ve iptallerde, imzayı bir ajan atıyorsa bu anahtar ajanınkidir; ajan onayı ve yetki kaldırmada ise sahip cüzdanınkidir.
- Bir nonce yeniden kullanılamaz. Emir nonce'ları
POST /order, toplu emirler ve WebSocketPlaceOrderarasında ortaktır; bir kanalda kullanılan nonce başka bir kanalda yeniden kullanılamaz. - Boşluklara izin verilir. Engine, imzalayan başına en son 100 nonce'u tutar ve 100'e ulaştığında yeni nonce, tutulan en küçük nonce'tan büyük olmalıdır.
En iyi uygulamalar:
- Başlangıç değerini milisaniye epoch zamanından alın ve imzalayan başına son nonce'u kalıcı olarak saklayarak
max(now_ms, last + 1)döndürün - Aynı anahtarla imza atan tüm süreçlerde tek bir nonce üreticisi paylaşın
- Bir istek başarısız olursa, yeni bir nonce ile tekrar imzalayın
Ajan Yetkilendirmesi
İmzalama için bir ajan cüzdanı kullanıyorsanız:
-
Ajanı onaylayın (tek seferlik):
POST /approve-agent{"agent": "0x...","nonce": 1791273600000,"signature": "0x..." # Signed by wallet owner} -
Emirleri ajan cüzdanıyla imzalayın:
PlaceOrder/CancelOrdermesajlarını imzalamak için ajan cüzdanını kullanınwalletalanını işlem yapılan cüzdan adresine ayarlayın- Middleware, ajanın o cüzdan için yetkili olduğunu doğrular
Ajan yetkilendirmesinin tüm ayrıntıları için Ajan yetkilendirmesi sayfasına bakın.
Perp Emirleri
Perp emirleri yukarıdaki Hypercall domain'ini kullanmaz. Bunlar, Hypercall Hesabınıza kayıtlı bir API cüzdanı tarafından HypercallApiSign domain'inde (chain ID 999, sıfır verifying contract) bir HLOrder olarak imzalanır. Struct ve birimler için EIP-712 İmzalama sayfasına bakın.
TEE yolu API üzerinden isteğe bağlıdır: TEE endpoint'lerini çağırarak bu yolu seçersiniz. Hypercall uygulamasında ise varsayılandır. Kullanmak için imzalı emri account, nonce, action ve signature ile birlikte POST /v1/tee-perp/orders/submit adresine gönderin. Hypercall teminat kontrolünü yapar, ardından güvenli bir enclave Hesabınız için yerel Hyperliquid emrini imzalayıp gönderir. Her perp emri %0 ücretli Hypercall builder kodunu taşır; bu nedenle Hesap yöneticisinin ilk emirden önce bu builder'ı bir kez onaylaması gerekir (uygulamadaki Enable trading adımı). Onay olmadan emir builder_not_approved hatasıyla reddedilir. Akış için Perps, istek ve yanıt şeması için API Referansı sayfalarına bakın.
Hyperliquid'in kendi Exchange domain'i (chain ID 1337, MessagePack Agent payload'ları) Hypercall API tarafından kabul edilmez.
Yaygın Hatalar
unauthorized (HTTP 401): "Signer 0x... is not authorized to act for wallet 0x..."
EIP-712 geri elde etme işlemi her zaman bir adres üretir. İmzaladığınız herhangi bir şey gönderdiğinizden farklıysa, geri elde edilen adres sizin anahtarınız olmaz ve istek bir imza hatası yerine burada başarısız olur.
Nedenler:
priceveyasizestring biçimlendirmesi imzalama ile gönderme arasında değişti (ör."100.0"ile"100")- İmzalanan bir alan JSON gövdesinden farklı (
route,clientId/client_id,nonce,tif), ya darouteimzalandı ancak gövdede yok, veya tam tersi - Yanlış domain (chain ID, name, version, verifying contract)
- İstek için yanlış struct (örneğin
PUT /orderiçinReplaceOrderyerinePlaceOrder) - İmzalayan gerçekten ne cüzdanın kendisi ne de onaylı bir ajan. Ajanı
POST /approve-agentile onaylayın veya doğrudan cüzdanla imzalayın
Mesaj tanımadığınız bir imzalayan adresi gösteriyorsa, neden 1 ile 4 arasındakilerden biridir.
signature_verification_failed (HTTP 400)
Neden: İmza hiç çözümlenemedi veya geri elde edilemedi; örneğin uzunluk yanlış ya da hex geçersiz.
invalid_parameter (HTTP 400): "price must be provided as a string for signature verification"
Neden: price veya size JSON sayısı olarak gönderildi. Her ikisini de string olarak gönderin.
Uygulama Örnekleri
Python (eth_account 0.10 veya üzeri)
import time
from eth_account import Account
from eth_account.messages import encode_typed_data
domain = {
"name": "Hypercall",
"version": "1",
"chainId": 999,
"verifyingContract": "0x0000000000000000000000000000000000000000"
}
message = {
"wallet": "0x1111111111111111111111111111111111111111",
"symbol": "BTC-20250131-100000-C",
"side": "Buy",
"size": "0.1",
"price": "100.0",
"tif": "gtc",
"route": "best_execution",
"clientId": "mm-1",
"nonce": int(time.time() * 1000) # current ms epoch; send this exact value in the body
}
types = {
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "verifyingContract", "type": "address"}
],
"PlaceOrder": [
{"name": "wallet", "type": "address"},
{"name": "symbol", "type": "string"},
{"name": "side", "type": "string"},
{"name": "size", "type": "string"},
{"name": "price", "type": "string"},
{"name": "tif", "type": "string"},
{"name": "route", "type": "string"},
{"name": "clientId", "type": "string"},
{"name": "nonce", "type": "uint64"}
]
}
structured_msg = {
"types": types,
"domain": domain,
"primaryType": "PlaceOrder",
"message": message
}
encoded = encode_typed_data(full_message=structured_msg)
signed = Account.sign_message(encoded, private_key)
signature = signed.signature.hex()
JavaScript (ethers.js v6)
const { ethers } = require("ethers");
const domain = {
name: "Hypercall",
version: "1",
chainId: 999,
verifyingContract: "0x0000000000000000000000000000000000000000"
};
const types = {
PlaceOrder: [
{ name: "wallet", type: "address" },
{ name: "symbol", type: "string" },
{ name: "side", type: "string" },
{ name: "size", type: "string" },
{ name: "price", type: "string" },
{ name: "tif", type: "string" },
{ name: "route", type: "string" },
{ name: "clientId", type: "string" },
{ name: "nonce", type: "uint64" }
]
};
const message = {
wallet: "0x1111111111111111111111111111111111111111",
symbol: "BTC-20250131-100000-C",
side: "Buy",
size: "0.1",
price: "100.0",
tif: "gtc",
route: "best_execution",
clientId: "mm-1",
nonce: Date.now() // current ms epoch; send this exact value in the body
};
const signature = await signer.signTypedData(domain, types, message);
İmzaları Test Etme
İmza üretimini test etmek için örnek:
- Kendi uygulamanızla imza üretin
POST /orderile test emri gönderin- Yanıtı doğrulayın:
statusdeğeri"ACKED"olan HTTP 200 ya dareasoniçeren"REJECTED" - İstek, tanımadığınız bir imzalayan adresiyle HTTP 401
unauthorizedveya HTTP 400signature_verification_failedhatasıyla başarısız olursa şunları kontrol edin:pricevesizealanlarının string biçimlendirmesi- Domain parametreleri (özellikle
chainId) routevenoncedahil, imzalanan her alanın gövdeyle eşleşmesi
Güvenlik Hususları
- Özel anahtarları asla açığa çıkarmayın: Donanım cüzdanları veya güvenli anahtar yönetimi kullanın
- Nonce yönetimi: İmzalama anahtarı başına kalıcı, milisaniye zaman damgalı nonce'lar kullanın
- Ajan yetkilendirmesi: Yetkili ajanları
GET /authorized-agentsile düzenli olarak denetleyin - String kodlaması:
pricevesizealanlarının hem imzalamada hem de istekte string olduğundan emin olun
Referanslar
- EIP-712: https://eips.ethereum.org/EIPS/eip-712
- Uygulama: imza geri elde etme ve middleware katmanı tarafından yürütülür.