@layerzerolabs/hyperliquid-composer
Version:
LayerZero Labs reference EVM OmniChain Fungible Token (OFT) implementation for Hyperliquid
551 lines (532 loc) • 21.4 kB
text/typescript
import { Wallet, ethers } from 'ethers';
import { Hex } from '@layerzerolabs/lz-utilities';
import { LogLevel, Logger } from '@layerzerolabs/io-devtools';
import dotenv from 'dotenv';
declare function useBigBlock(wallet: Wallet, isTestnet: boolean, logLevel: string): Promise<any>;
declare function useSmallBlock(wallet: Wallet, isTestnet: boolean, logLevel: string): Promise<any>;
interface BaseInfoRequest {
type: string;
[key: string]: unknown;
}
/** Base structure for exchange requests. */
interface BaseExchangeRequest {
/** Action to perform. */
action: {
/** Type of action. */
type: string;
/** Additional action parameters. */
[key: string]: unknown;
};
/** Unique request identifier (recommended current timestamp in ms). */
nonce: number;
/** Cryptographic signature. */
signature: {
r: Hex;
s: Hex;
v: number;
};
}
/** Base structure for exchange responses. */
interface BaseExchangeResponse {
/** Response status */
status: 'ok' | 'err';
/** Error message or success data */
response: string | {
/** Type of response. */
type: string;
/** Specific data for the operation. */
data?: unknown;
};
}
interface Signature {
r: string;
s: string;
v: number;
}
type ValueType = number | bigint | string | boolean | null | Uint8Array | readonly ValueType[] | ValueMap | BaseInfoRequest;
interface ValueMap {
[key: string]: ValueType;
}
declare const HYPERLIQUID_URLS: {
MAINNET: string;
TESTNET: string;
};
declare const RPC_URLS: {
MAINNET: string;
TESTNET: string;
};
declare const CHAIN_IDS: {
MAINNET: number;
TESTNET: number;
};
declare const ENDPOINTS: {
INFO: string;
EXCHANGE: string;
};
declare const MAX_HYPERCORE_SUPPLY: number;
/**
* These are the token ids for USDC on hypercore mainnet and testnet
* It can be reproduced by grabbing the entire spotMeta and finding USDC because Hyperliquid does not have an API to target query an asset (April 8, 2025)
* - curl -X POST "https://api.hyperliquid.xyz/info" -H "Content-Type: application/json" -d '{"type": "spotMeta"}' > spotOut.json
* - Goto tokens and the first entry should be USDC with an index of 0
*/
declare const USDC_TOKEN_ID: {
MAINNET: number;
TESTNET: number;
};
declare const USDT0_TOKEN_ID: {
MAINNET: number;
TESTNET: number;
};
declare function toAssetBridgeAddress(tokenIndex: number): string;
interface CoreSpotMetaData {
name: string;
szDecimals: number;
weiDecimals: number;
index: number;
tokenId: string;
isCanonical: boolean;
evmContract: null | {
address: string;
evm_extra_wei_decimals: number;
};
fullName: string | null;
deployerTradingFeeShare: string;
freezePrivilegeEnabled?: boolean;
quoteAssetEnabled?: boolean;
}
interface TxData {
from: string;
txHash: string;
nonce: number;
weiDiff: number;
assetBridgeAddress: string;
connected: boolean;
}
interface UserGenesis$1 {
userAndWei: Array<{
address: string;
wei: string;
}>;
existingTokenAndWei: Array<{
token: number;
wei: string;
}>;
blacklistUsers: string[];
}
interface CoreSpotDeployment {
coreSpot: CoreSpotMetaData;
txData: TxData;
userGenesis: UserGenesis$1;
}
interface SpotMeta {
tokens: CoreSpotMetaData[];
}
type SpotInfoBalance = [address: string, balance: string];
interface SpotInfo {
name: string;
maxSupply: string;
totalSupply: string;
circulatingSupply: string;
szDecimals: number;
weiDecimals: number;
midPx: string;
markPx: string;
prevDayPx: string;
genesis: {
userBalances: SpotInfoBalance[];
existingTokenBalances: SpotInfoBalance[];
};
deployer: string;
deployGas: string;
deployTime: string;
seededUsdc: string;
nonCirculatingUserBalances: SpotInfoBalance[];
futureEmissions: string;
}
interface DeployState {
token: number;
spec: {
name: string;
szDecimals: number;
weiDecimals: number;
};
fullName: string | null;
spots: number[];
maxSupply: number;
hyperliquidityGenesisBalance: string;
totalGenesisBalanceWei: string;
userGenesisBalances: [string, string][];
existingTokenGenesisBalances: [number, string][];
}
interface GasAuction {
startTimeSeconds: number;
durationSeconds: number;
startGas: string;
currentGas: string | null;
endGas: string;
}
interface SpotDeployStates {
states: DeployState[];
gasAuction: GasAuction;
}
interface SpotBalance {
coin: string;
token: number;
total: string;
hold: string;
entryNtl: string;
}
interface SpotBalancesResponse {
balances: SpotBalance[];
}
interface SpotPair {
tokens: number[];
name: string;
index: number;
isCanonical: boolean;
}
interface SpotMetaUniverse {
universe: SpotPair[];
tokens: CoreSpotMetaData[];
}
interface SpotPairsWithMetadata {
pairs: SpotPair[];
tokens: CoreSpotMetaData[];
}
interface SpotPairDeployAuctionStatus {
startTimeSeconds: number;
durationSeconds: number;
startGas: string;
currentGas: string;
endGas: string | null;
}
/**
* This is an optional action that can be performed at any time after
* RegisterToken2. While the fee share defaults to 100%, this action
* can be resent multiple times as long as the fee share is not increasing.
* @param token - The token
* @param share - The deployer trading fee share. Range: ["0%", "100%"]. Examples: "0.012%", "99.4%"
*/
interface SetDeployerTradingFeeShare {
token: number;
share: string;
}
/**
* UserGenesis can be called multiple times
* @param token - The token involved in the genesis.
* @param userAndWei - A list of tuples of user address and genesis amount (wei).
* @param existingTokenAndWei - A list of tuples of existing token and total genesis amount for holders of that token (wei).
* @param blacklistUsers - A list of tuples of users and blacklist status (True if blacklist, False to remove existing blacklisted user).
*/
interface UserGenesis {
token: number;
userAndWei: Array<[string, string]>;
existingTokenAndWei: Array<[number, string]>;
blacklistUsers?: Array<[string, boolean]>;
}
/**
* Genesis denotes the initial creation of a token with a maximum supply.
* @param maxSupply - Checksum ensureing all calls to UserGenesis succeeded
* @param noHyperliquidity - Set hyperliquidity balance to 0.
*/
interface Genesis {
token: number;
maxSupply: string;
noHyperliquidity: boolean;
}
/**
* @param tokens - [base token index, quote token index]
* @dev The base token index is the token index of the token that will be used as the base for the spot.
* @dev The quote token index is the token index of the token that will be used as the quote for the spot - this is the token that will be used to pay the trading fee like USDC.
*/
interface RegisterSpot {
tokens: [number, number];
}
/**
* @param spot - The spot index (different from base token index)
* @param startPx - The starting price.
* @param orderSz - The size of each order (float, not wei)
* @param nOrders - The number of orders. If "noHyperliquidity" was set to True, then this must be 0.
* @param nSeededLevels - The number of levels the deployer wishes to seed with usdc instead of tokens.
*/
interface RegisterHyperliquidity {
spot: number;
startPx: string;
orderSz: string;
nOrders: number;
nSeededLevels?: number;
}
/**
* Enables freeze privilege for a token, allowing the deployer to freeze/unfreeze users
* @param token - The token index
*/
interface EnableFreezePrivilege {
token: number;
}
/**
* Freezes or unfreezes a specific user for a token
* @param token - The token index
* @param user - The user address to freeze/unfreeze
* @param freeze - True to freeze, false to unfreeze
*/
interface FreezeUser {
token: number;
user: string;
freeze: boolean;
}
/**
* Revokes freeze privilege for a token, permanently disabling the ability to freeze users
* @param token - The token index
*/
interface RevokeFreezePrivilege {
token: number;
}
/**
* Enables a token to be used as a quote asset in trading pairs
* @param token - The token index
*/
interface EnableQuoteToken {
token: number;
}
interface EvmUserModifyRequest extends BaseExchangeRequest {
action: {
type: 'evmUserModify';
usingBigBlocks: boolean;
};
}
interface EvmSpotDeploy extends BaseExchangeRequest {
action: {
type: 'spotDeploy';
requestEvmContract: {
token: number;
address: string;
evmExtraWeiDecimals: number;
};
};
}
interface FinalizeEvmContract extends BaseExchangeRequest {
action: {
type: 'finalizeEvmContract';
token: number;
input: {
create: {
nonce: number;
};
};
};
}
interface SpotDeployAction extends BaseExchangeRequest {
action: {
type: 'spotDeploy';
setDeployerTradingFeeShare: SetDeployerTradingFeeShare;
} | {
type: 'spotDeploy';
userGenesis: UserGenesis;
} | {
type: 'spotDeploy';
genesis: Genesis;
} | {
type: 'spotDeploy';
registerSpot: RegisterSpot;
} | {
type: 'spotDeploy';
registerHyperliquidity: RegisterHyperliquidity;
} | {
type: 'spotDeploy';
enableFreezePrivilege: EnableFreezePrivilege;
} | {
type: 'spotDeploy';
freezeUser: FreezeUser;
} | {
type: 'spotDeploy';
revokeFreezePrivilege: RevokeFreezePrivilege;
} | {
type: 'spotDeploy';
enableQuoteToken: EnableQuoteToken;
};
}
interface SpotClearinghouseState extends BaseExchangeRequest {
action: {
type: 'spotClearinghouseState';
user: string;
};
}
/**
* Type definitions for CLI command arguments
* These replace the `any` types used throughout the command functions
*/
interface BaseArgs {
network: 'mainnet' | 'testnet';
logLevel: LogLevel;
}
interface TokenIndexArgs extends BaseArgs {
tokenIndex: string;
}
interface PrivateKeyArgs extends BaseArgs {
privateKey?: string;
}
interface UserArgs extends BaseArgs {
user: string;
}
interface OptionalOAppArgs extends BaseArgs {
oappConfig?: string;
}
interface SetBlockArgs extends PrivateKeyArgs {
size: 'big' | 'small';
}
interface CoreSpotDeploymentArgs extends TokenIndexArgs, OptionalOAppArgs {
action: 'create' | 'get';
}
interface UserGenesisArgs extends TokenIndexArgs, PrivateKeyArgs {
action: '*' | 'userAndWei' | 'existingTokenAndWei' | 'blacklistUsers';
}
interface TradingFeeArgs extends TokenIndexArgs, PrivateKeyArgs {
share: string;
}
interface FreezeUserArgs extends TokenIndexArgs, PrivateKeyArgs {
userAddress: string;
freeze: 'true' | 'false';
}
interface SpotDeployStateArgs extends TokenIndexArgs {
deployerAddress?: string;
}
interface GetCoreBalancesArgs extends UserArgs {
showZero: boolean;
}
interface GenesisArgs extends TokenIndexArgs, PrivateKeyArgs {
}
interface CreateSpotDeploymentArgs extends TokenIndexArgs, PrivateKeyArgs {
}
interface RegisterTradingSpotArgs extends TokenIndexArgs, PrivateKeyArgs {
}
interface EnableTokenFreezePrivilegeArgs extends TokenIndexArgs, PrivateKeyArgs {
}
interface RevokeTokenFreezePrivilegeArgs extends TokenIndexArgs, PrivateKeyArgs {
}
interface EnableTokenQuoteAssetArgs extends TokenIndexArgs, PrivateKeyArgs {
}
interface RequestEvmContractArgs extends TokenIndexArgs, PrivateKeyArgs, OptionalOAppArgs {
}
interface FinalizeEvmContractArgs extends TokenIndexArgs, PrivateKeyArgs, OptionalOAppArgs {
}
declare function getSpotMeta(wallet: Wallet | null, isTestnet: boolean, logLevel: string, tokenIndex: string): Promise<CoreSpotMetaData>;
declare function getHipTokenInfo(wallet: Wallet | null, isTestnet: boolean, logLevel: string, tokenAddress: string): Promise<SpotInfo>;
declare function getSpotDeployState(deployerAddres: string, isTestnet: boolean, logLevel: string): Promise<SpotDeployStates>;
/**
* Gets all spot trading pairs for a given coreSpot token index.
* This function fetches the complete spotMeta universe and filters for pairs
* that include the specified token index.
*
* @param isTestnet Whether to query testnet or mainnet
* @param tokenIndex The token index to find pairs for
* @param logLevel Logging level for the client
* @returns Array of spot pairs that include the specified token
*/
declare function getSpotPairs(isTestnet: boolean, tokenIndex: number, logLevel: string): Promise<SpotPair[]>;
/**
* Gets all spot trading pairs for a given coreSpot token index along with token metadata.
* This function fetches both the pairs and token metadata for name resolution.
*
* @param isTestnet Whether to query testnet or mainnet
* @param tokenIndex The token index to find pairs for
* @param logLevel Logging level for the client
* @returns Object containing filtered pairs and token metadata
*/
declare function getSpotPairsWithMetadata(isTestnet: boolean, tokenIndex: number, logLevel: string): Promise<SpotPairsWithMetadata>;
/**
* Gets the current spot pair deploy auction status.
* This shows information about the ongoing auction for spot pair deployments.
*
* @param isTestnet Whether to query testnet or mainnet
* @param logLevel Logging level for the client
* @returns Current auction status information
*/
declare function getSpotPairDeployAuctionStatus(isTestnet: boolean, logLevel: string): Promise<SpotPairDeployAuctionStatus>;
/**
* Gets the quote tokens that a given core spot token is already paired with.
* This is useful to check what trading pairs already exist before deploying new ones.
*
* @param isTestnet Whether to query testnet or mainnet
* @param tokenIndex The token index to check existing pairs for
* @param logLevel Logging level for the client
* @returns Array of quote token indices that the token is already paired with
*/
declare function getExistingQuoteTokens(isTestnet: boolean, tokenIndex: number, logLevel: string): Promise<number[]>;
declare function setTradingFeeShare(wallet: Wallet, isTestnet: boolean, coreSpotTokenId: number, share: string, logLevel: string): Promise<any>;
declare function setUserGenesis(wallet: Wallet, isTestnet: boolean, coreSpotTokenId: number, action: string, logLevel: string): Promise<{
responseForUserGenesis: {};
responseForBlacklistUsers: {};
}>;
declare function setGenesis(wallet: Wallet, isTestnet: boolean, coreSpotTokenId: number, logLevel: string): Promise<any>;
declare function setNoHyperliquidity(wallet: Wallet, isTestnet: boolean, tokenIndex: number, logLevel: string): Promise<any>;
declare function registerSpot(wallet: Wallet, isTestnet: boolean, coreSpotTokenId: number, logLevel: string): Promise<any>;
declare function enableFreezePrivilege(wallet: Wallet, isTestnet: boolean, coreSpotTokenId: number, logLevel: string): Promise<any>;
declare function freezeUser(wallet: Wallet, isTestnet: boolean, coreSpotTokenId: number, userAddress: string, freeze: boolean, logLevel: string): Promise<any>;
declare function revokeFreezePrivilege(wallet: Wallet, isTestnet: boolean, coreSpotTokenId: number, logLevel: string): Promise<any>;
declare function enableQuoteToken(wallet: Wallet, isTestnet: boolean, coreSpotTokenId: number, logLevel: string): Promise<any>;
declare function setRequestEvmContract(wallet: Wallet, isTestnet: boolean, evmSpotTokenAddress: string, evmExtraWeiDecimals: number, coreSpotTokenId: number, logLevel: string): Promise<any>;
declare function setFinalizeEvmContract(wallet: Wallet, isTestnet: boolean, coreSpotTokenId: number, nonce: number, logLevel: string): Promise<any>;
declare function spotClearinghouseState(user: string, isTestnet: boolean, logLevel: string): Promise<SpotBalancesResponse>;
/**
* @dev Creates a keccak hash based on the packed action, nonce, and vault address.
* @dev I just ripped off - https://github.com/hyperliquid-dex/hyperliquid-python-sdk/blob/master/hyperliquid/utils/signing.py#L137-L145
*
* @param action - The action data to be packed with MessagePack.
* @param vaultAddress - The vault address as a hex string or null.
* @param nonce - A numeric nonce.
*
* @returns The keccak hash as a hex string.
*/
declare function computeL1ActionHash(action: ValueType, nonce: number, vaultAddress: string | null): string;
/**
* Sign an L1 action.
*
* @dev Signature generation depends on the order of the action keys.
* @dev I just ripped off - https://github.com/hyperliquid-dex/hyperliquid-python-sdk/blob/master/hyperliquid/utils/signing.py#L152-L177
*
* @param args.wallet - Wallet to sign the action.
* @param args.action - The action to be signed.
* @param args.nonce - Unique request identifier (recommended current timestamp in ms).
* @param args.isTestnet - Indicates if the action is for the testnet. Default is `false`.
* @param args.vaultAddress - Optional vault address used in the action.
*
* @returns The signature components r, s, and v.
*/
declare function signL1Action(args: {
wallet: Wallet;
action: ValueType;
nonce: number;
isTestnet?: boolean;
vaultAddress: Hex | null;
}): Promise<{
r: Hex;
s: Hex;
v: number;
}>;
declare function getTimestampMs(): number;
declare function getHyperliquidWallet(privateKey?: string): Promise<ethers.Wallet>;
declare class HyperliquidClient {
private readonly client;
private readonly baseUrl;
private readonly isTestnet;
private readonly logger;
constructor(isTestnet: boolean, logLevel: string);
submitHyperliquidAction(endpoint: string, wallet: Wallet | null, action: ValueType): Promise<any>;
}
declare function getCoreSpotDeployment(index: string | number, isTestnet: boolean, logger?: Logger): CoreSpotDeployment;
declare function writeCoreSpotDeployment(index: string | number, isTestnet: boolean, coreSpotDeployment: CoreSpotDeployment, logger?: Logger): void;
declare function writeUpdatedCoreSpotDeployment(index: string | number, isTestnet: boolean, tokenFullName: string, tokenAddress: string, txData: TxData, logger?: Logger): void;
declare function writeNativeSpotConnected(index: string | number, isTestnet: boolean, connected: boolean, weiDiff: number, logger?: Logger): void;
declare function updateFreezePrivilegeStatus(index: string | number, isTestnet: boolean, enabled: boolean, logger?: Logger): void;
declare function updateQuoteTokenStatus(index: string | number, isTestnet: boolean, enabled: boolean, logger?: Logger): void;
declare function updateUserFreezeStatus(index: string | number, isTestnet: boolean, userAddress: string, frozen: boolean, logger?: Logger): void;
declare function getHyperEVMOAppDeployment(oapp_config: string, network: string, logger?: Logger): Promise<{
contractName: string;
deployment: string;
}>;
declare function getERC20abi(): Promise<any>;
declare function loadEnv(): dotenv.DotenvParseOutput;
declare function formatBalancesTable(balances: SpotBalancesResponse, showZeroBalances: boolean): string;
declare function formatSpotPairsTable(data: SpotPairsWithMetadata, tokenIndex: number): string;
export { type BaseArgs, type BaseExchangeRequest, type BaseExchangeResponse, type BaseInfoRequest, CHAIN_IDS, type CoreSpotDeployment, type CoreSpotDeploymentArgs, type CoreSpotMetaData, type CreateSpotDeploymentArgs, type DeployState, ENDPOINTS, type EnableTokenFreezePrivilegeArgs, type EnableTokenQuoteAssetArgs, type EvmSpotDeploy, type EvmUserModifyRequest, type FinalizeEvmContract, type FinalizeEvmContractArgs, type FreezeUserArgs, type GasAuction, type GenesisArgs, type GetCoreBalancesArgs, HYPERLIQUID_URLS, HyperliquidClient, MAX_HYPERCORE_SUPPLY, type OptionalOAppArgs, type PrivateKeyArgs, RPC_URLS, type RegisterTradingSpotArgs, type RequestEvmContractArgs, type RevokeTokenFreezePrivilegeArgs, type SetBlockArgs, type Signature, type SpotBalance, type SpotBalancesResponse, type SpotClearinghouseState, type SpotDeployAction, type SpotDeployStateArgs, type SpotDeployStates, type SpotInfo, type SpotInfoBalance, type SpotMeta, type SpotMetaUniverse, type SpotPair, type SpotPairDeployAuctionStatus, type SpotPairsWithMetadata, type TokenIndexArgs, type TradingFeeArgs, type TxData, USDC_TOKEN_ID, USDT0_TOKEN_ID, type UserArgs, type UserGenesis$1 as UserGenesis, type UserGenesisArgs, type ValueMap, type ValueType, computeL1ActionHash, enableFreezePrivilege, enableQuoteToken, formatBalancesTable, formatSpotPairsTable, freezeUser, getCoreSpotDeployment, getERC20abi, getExistingQuoteTokens, getHipTokenInfo, getHyperEVMOAppDeployment, getHyperliquidWallet, getSpotDeployState, getSpotMeta, getSpotPairDeployAuctionStatus, getSpotPairs, getSpotPairsWithMetadata, getTimestampMs, loadEnv, registerSpot, revokeFreezePrivilege, setFinalizeEvmContract, setGenesis, setNoHyperliquidity, setRequestEvmContract, setTradingFeeShare, setUserGenesis, signL1Action, spotClearinghouseState, toAssetBridgeAddress, updateFreezePrivilegeStatus, updateQuoteTokenStatus, updateUserFreezeStatus, useBigBlock, useSmallBlock, writeCoreSpotDeployment, writeNativeSpotConnected, writeUpdatedCoreSpotDeployment };