账户抽象模式
用户的账户抽象模式决定了现货和永续合约余额如何交互,以及各种资产是否用作永续合约交易的抵押品。
支持的模式有:
- 统一账户(推荐大多数用户使用):每种资产单一余额。该余额为该资产的所有全仓仓位提供抵押,并与该资产的现货余额统一。例如,USDC 余额是验证者运营的永续合约、XYZ 永续合约以及以 USDC 为计价资产的现货交易的唯一来源。USDT 现货余额是 CASH 永续合约以及以 USDT 为计价资产的现货交易的唯一来源。
- 投资组合保证金(资金效率最高):统一所有合格资产(目前为 HYPE、BTC、USDC、USDT)的单一投资组合。更多详情请参见投资组合保证金。
- 手动 / 标准(推荐做市商、高频自动化用户以及部署者/Builder 使用):永续合约和现货余额分开,各 DEX 余额分开。全仓保证金分别适用于每个 DEX。
还有一种已停用的模式,为完整起见在此列出:
- DEX 抽象(已停用):USDC 余额默认为永续合约余额,所有其他抵押品默认为现货余额。重要提示:对于 DEX 抽象用户,HIP-3 DEX 上的全仓保证金行为并不直观。
重要细节:
- Builder Code 地址必须处于标准模式才能累积 Builder 费用
- 投资组合保证金和统一账户每天限 5 万次用户操作。标准模式没有此类限制。
- 对于 API 用户,统一账户和投资组合保证金会在现货清算所状态中显示所有余额和持有量。各个永续合约 dex 的用户状态不再有意义。
有关切换账户抽象模式的代理签名和用户签名操作的示例,请参见 Python SDK 和 API 文档。
统一账户比率
用于监控清算风险的精确统一账户比率的计算方法如下:
function computeUnifiedAccountRatio(
multiverse: Record<string, { index: number; collateralToken: number }>,
perpDexStates: Array<{
clearinghouseState: {
crossMaintenanceMarginUsed: number;
assetPositions: Array<{
position: { leverage: { type: string }; marginUsed: number };
}>;
};
}>,
spotBalances: Array<{ token: number; total: number }>,
): number {
const indexToCollateralToken: Record<number, number> = {};
for (const meta of Object.values(multiverse)) {
indexToCollateralToken[meta.index] = meta.collateralToken;
}
const crossMarginByToken: Record<number, number> = {};
const isolatedMarginByToken: Record<number, number> = {};
for (let index = 0; index < perpDexStates.length; index++) {
const dex = perpDexStates[index];
const token = indexToCollateralToken[index];
if (dex === undefined || token === undefined) continue;
crossMarginByToken[token] =
(crossMarginByToken[token] ?? 0) +
dex.clearinghouseState.crossMaintenanceMarginUsed;
for (const ap of dex.clearinghouseState.assetPositions) {
if (ap.position.leverage.type === "isolated") {
isolatedMarginByToken[token] =
(isolatedMarginByToken[token] ?? 0) + ap.position.marginUsed;
}
}
}
let maxRatio = 0;
for (const [tokenStr, crossMargin] of Object.entries(crossMarginByToken)) {
const token = Number(tokenStr);
const spotTotal = spotBalances.find((b) => b.token === token)?.total ?? 0;
const isolatedMargin = isolatedMarginByToken[token] ?? 0;
const available = spotTotal - isolatedMargin;
if (available > 0) {
maxRatio = Math.max(maxRatio, crossMargin / available);
}
}
return maxRatio;
}