UNPKG

hyperliquid

Version:
1 lines 278 kB
{"version":3,"sources":["../src/types/constants.ts","../src/rest/info/general.ts","../src/rest/info/spot.ts","../src/rest/info/perpetuals.ts","../src/utils/helpers.ts","../src/utils/errors.ts","../src/rest/info.ts","../src/rest/exchange.ts","../src/utils/signing.ts","../src/utils/environment.ts","../src/websocket/connection.ts","../src/websocket/subscriptions.ts","../src/websocket/payload-generator.ts","../src/websocket/payload-manager.ts","../src/utils/rateLimiter.ts","../src/rest/custom.ts","../src/index.ts","../src/utils/symbolConversion.ts"],"sourcesContent":["export const BASE_URLS = {\n PRODUCTION: 'https://api.hyperliquid.xyz',\n TESTNET: 'https://api.hyperliquid-testnet.xyz',\n};\n\nexport const WSS_URLS = {\n PRODUCTION: 'wss://api.hyperliquid.xyz/ws',\n TESTNET: 'wss://api.hyperliquid-testnet.xyz/ws',\n};\n\nexport const CHAIN_IDS = {\n ARBITRUM_MAINNET: '0xa4b1', // 42161\n ARBITRUM_TESTNET: '0x66eee', // 421614 - testnet//Arbitrum Sepolia\n};\n\nexport const ENDPOINTS = {\n INFO: '/info',\n EXCHANGE: '/exchange',\n};\n\nexport enum InfoType {\n ALL_MIDS = 'allMids',\n META = 'meta',\n OPEN_ORDERS = 'openOrders',\n FRONTEND_OPEN_ORDERS = 'frontendOpenOrders',\n USER_FILLS = 'userFills',\n USER_FILLS_BY_TIME = 'userFillsByTime',\n USER_RATE_LIMIT = 'userRateLimit',\n ORDER_STATUS = 'orderStatus',\n L2_BOOK = 'l2Book',\n CANDLE_SNAPSHOT = 'candleSnapshot',\n PERPS_META_AND_ASSET_CTXS = 'metaAndAssetCtxs',\n PERPS_CLEARINGHOUSE_STATE = 'clearinghouseState',\n USER_FUNDING = 'userFunding',\n USER_NON_FUNDING_LEDGER_UPDATES = 'userNonFundingLedgerUpdates',\n FUNDING_HISTORY = 'fundingHistory',\n SPOT_META = 'spotMeta',\n SPOT_CLEARINGHOUSE_STATE = 'spotClearinghouseState',\n SPOT_META_AND_ASSET_CTXS = 'spotMetaAndAssetCtxs',\n PREDICTED_FUNDINGS = 'predictedFundings',\n SPOT_DEPLOY_STATE = 'spotDeployState',\n TOKEN_DETAILS = 'tokenDetails',\n MAX_BUILDER_FEE = 'maxBuilderFee',\n HISTORICAL_ORDERS = 'historicalOrders',\n USER_TWAP_SLICE_FILLS = 'userTwapSliceFills',\n SUB_ACCOUNTS = 'subAccounts',\n VAULT_DETAILS = 'vaultDetails',\n USER_VAULT_EQUITIES = 'userVaultEquities',\n USER_ROLE = 'userRole',\n DELEGATIONS = 'delegations',\n DELEGATOR_SUMMARY = 'delegatorSummary',\n PERPS_AT_OPEN_INTEREST_CAP = 'perpsAtOpenInterestCap',\n DELEGATOR_HISTORY = 'delegatorHistory',\n DELEGATOR_REWARDS = 'delegatorRewards',\n VALIDATOR_SUMMARIES = 'validatorSummaries',\n VAULT_SUMMARIES = 'vaultSummaries',\n BLOCK_DETAILS = 'blockDetails',\n TX_DETAILS = 'txDetails',\n USER_DETAILS = 'userDetails',\n USER_FEES = 'userFees',\n PORTFOLIO = 'portfolio',\n PRE_TRANSFER_CHECK = 'preTransferCheck',\n REFERRAL = 'referral',\n EXTRA_AGENTS = 'extraAgents',\n IS_VIP = 'isVip',\n LEGAL_CHECK = 'legalCheck',\n USER_TWAP_SLICE_FILLS_BY_TIME = 'userTwapSliceFillsByTime',\n TWAP_HISTORY = 'twapHistory',\n USER_TO_MULTI_SIG_SIGNERS = 'userToMultiSigSigners',\n BUILDER_FEE_APPROVAL = 'builderFeeApproval',\n USER_ORDER_HISTORY = 'userOrderHistory',\n PERP_DEX_LIMITS = 'perpDexLimits',\n}\n\nexport enum ExchangeType {\n ORDER = 'order',\n CANCEL = 'cancel',\n CANCEL_BY_CLOID = 'cancelByCloid',\n SCHEDULE_CANCEL = 'scheduleCancel',\n MODIFY = 'modify',\n BATCH_MODIFY = 'batchModify',\n UPDATE_LEVERAGE = 'updateLeverage',\n UPDATE_ISOLATED_MARGIN = 'updateIsolatedMargin',\n USD_SEND = 'usdSend',\n SPOT_SEND = 'spotSend',\n WITHDRAW = 'withdraw3',\n SPOT_USER = 'spotUser',\n VAULT_TRANSFER = 'vaultTransfer',\n CREATE_VAULT = 'createVault',\n VAULT_DISTRIBUTE = 'vaultDistribute',\n VAULT_MODIFY = 'vaultModify',\n SET_REFERRER = 'setReferrer',\n REGISTER_REFERRER = 'registerReferrer',\n USD_CLASS_TRANSFER = 'usdClassTransfer',\n TWAP_ORDER = 'twapOrder',\n TWAP_CANCEL = 'twapCancel',\n APPROVE_AGENT = 'approveAgent',\n APPROVE_BUILDER_FEE = 'approveBuilderFee',\n EVM_USER_MODIFY = 'evmUserModify',\n CLAIM_REWARDS = 'claimRewards',\n CREATE_SUB_ACCOUNT = 'createSubAccount',\n SET_DISPLAY_NAME = 'setDisplayName',\n C_DEPOSIT = 'cDeposit',\n C_WITHDRAW = 'cWithdraw',\n TOKEN_DELEGATE = 'tokenDelegate',\n SUB_ACCOUNT_SPOT_TRANSFER = 'subAccountSpotTransfer',\n SUB_ACCOUNT_TRANSFER = 'subAccountTransfer',\n RESERVE_REQUEST_WEIGHT = 'reserveRequestWeight',\n NOOP = 'noop',\n}\n\nexport const WEBSOCKET = {\n MAINNET_URL: 'wss://api.hyperliquid.xyz/ws',\n TESTNET_URL: 'wss://api.hyperliquid-testnet.xyz/ws',\n};\n\nexport const SDK_CODE = 'PLACEHOLDER';\n","// src/rest/info/general.ts\n\nimport {\n AllMids,\n UserOpenOrders,\n FrontendOpenOrders,\n UserFills,\n UserRateLimit,\n OrderStatus,\n L2Book,\n CandleSnapshot,\n HistoricalOrder,\n TwapSliceFill,\n SubAccount,\n VaultDetails,\n VaultEquity,\n UserRole,\n Delegation,\n DelegatorSummary,\n DelegatorHistoryEntry,\n DelegatorReward,\n ValidatorSummary,\n VaultSummary,\n UserFees,\n PortfolioPeriods,\n PreTransferCheck,\n Referral,\n ExtraAgent,\n LegalCheck,\n TwapHistory,\n MultiSigSigners,\n BuilderFeeApproval,\n UserOrderHistory,\n} from '../../types';\nimport { HttpApi } from '../../utils/helpers';\nimport { SymbolConversion } from '../../utils/symbolConversion';\nimport { InfoType } from '../../types/constants';\nimport { Hyperliquid } from '../../index';\n\nexport class GeneralInfoAPI {\n private parent: Hyperliquid;\n\n constructor(\n private httpApi: HttpApi,\n private symbolConversion: SymbolConversion,\n parent: Hyperliquid\n ) {\n this.parent = parent;\n }\n\n async getAllMids(rawResponse: boolean = false): Promise<AllMids> {\n const response = await this.httpApi.makeRequest<AllMids>({ type: InfoType.ALL_MIDS });\n\n if (rawResponse) {\n return response;\n } else {\n const convertedResponse: any = {};\n for (const [key, value] of Object.entries(response)) {\n const convertedKey = await this.symbolConversion.convertSymbol(key);\n const convertedValue = parseFloat(value as string);\n convertedResponse[convertedKey] = convertedValue;\n }\n return convertedResponse;\n }\n }\n\n async getUserOpenOrders(user: string, rawResponse: boolean = false): Promise<UserOpenOrders> {\n await this.parent.ensureInitialized();\n const response = await this.httpApi.makeRequest<UserOpenOrders>({\n type: InfoType.OPEN_ORDERS,\n user: user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getFrontendOpenOrders(\n user: string,\n rawResponse: boolean = false\n ): Promise<FrontendOpenOrders> {\n const response = await this.httpApi.makeRequest<FrontendOpenOrders>(\n { type: InfoType.FRONTEND_OPEN_ORDERS, user: user },\n 20\n );\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getUserFills(user: string, rawResponse: boolean = false): Promise<UserFills> {\n const response = await this.httpApi.makeRequest<UserFills>(\n { type: InfoType.USER_FILLS, user: user },\n 20\n );\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getUserFillsByTime(\n user: string,\n startTime: number,\n endTime?: number,\n rawResponse: boolean = false\n ): Promise<UserFills> {\n let params: { user: string; startTime: number; type: string; endTime?: number } = {\n user: user,\n startTime: Math.round(startTime),\n type: InfoType.USER_FILLS_BY_TIME,\n };\n\n if (endTime) {\n params.endTime = Math.round(endTime);\n }\n\n const response = await this.httpApi.makeRequest<UserFills>(params, 20);\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getUserRateLimit(user: string, rawResponse: boolean = false): Promise<UserRateLimit> {\n const response = await this.httpApi.makeRequest<UserRateLimit>(\n { type: InfoType.USER_RATE_LIMIT, user: user },\n 20\n );\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getOrderStatus(\n user: string,\n oid: number | string,\n rawResponse: boolean = false\n ): Promise<OrderStatus> {\n const response = await this.httpApi.makeRequest<OrderStatus>({\n type: InfoType.ORDER_STATUS,\n user: user,\n oid: oid,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getL2Book(\n coin: string,\n rawResponse: boolean = false,\n nSigFigs: number = 5,\n mantissa?: number\n ): Promise<L2Book> {\n const response = await this.httpApi.makeRequest<L2Book>({\n type: InfoType.L2_BOOK,\n coin: await this.symbolConversion.convertSymbol(coin, 'reverse'),\n nSigFigs,\n mantissa,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getCandleSnapshot(\n coin: string,\n interval: string,\n startTime: number,\n endTime: number,\n rawResponse: boolean = false\n ): Promise<CandleSnapshot> {\n const response = await this.httpApi.makeRequest<CandleSnapshot>({\n type: InfoType.CANDLE_SNAPSHOT,\n req: {\n coin: await this.symbolConversion.convertSymbol(coin, 'reverse'),\n interval: interval,\n startTime: startTime,\n endTime: endTime,\n },\n });\n\n return rawResponse ? response : await this.symbolConversion.convertResponse(response, ['s']);\n }\n\n // Add these methods to src/rest/info/general.ts\n\n async getMaxBuilderFee(\n user: string,\n builder: string,\n rawResponse: boolean = false\n ): Promise<number> {\n const response = await this.httpApi.makeRequest<number>({\n type: InfoType.MAX_BUILDER_FEE,\n user,\n builder,\n });\n return rawResponse ? response : this.symbolConversion.convertToNumber(response);\n }\n\n async getHistoricalOrders(\n user: string,\n rawResponse: boolean = false\n ): Promise<HistoricalOrder[]> {\n const response = await this.httpApi.makeRequest<HistoricalOrder[]>({\n type: InfoType.HISTORICAL_ORDERS,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getUserTwapSliceFills(\n user: string,\n rawResponse: boolean = false\n ): Promise<TwapSliceFill[]> {\n const response = await this.httpApi.makeRequest<TwapSliceFill[]>({\n type: InfoType.USER_TWAP_SLICE_FILLS,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getSubAccounts(user: string, rawResponse: boolean = false): Promise<SubAccount[]> {\n const response = await this.httpApi.makeRequest<SubAccount[]>({\n type: InfoType.SUB_ACCOUNTS,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getVaultDetails(\n vaultAddress: string,\n user?: string,\n rawResponse: boolean = false\n ): Promise<VaultDetails> {\n const params: any = {\n type: InfoType.VAULT_DETAILS,\n vaultAddress,\n };\n\n if (user) {\n params.user = user;\n }\n\n const response = await this.httpApi.makeRequest<VaultDetails>(params);\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getUserVaultEquities(user: string, rawResponse: boolean = false): Promise<VaultEquity[]> {\n const response = await this.httpApi.makeRequest<VaultEquity[]>({\n type: InfoType.USER_VAULT_EQUITIES,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getUserRole(user: string, rawResponse: boolean = false): Promise<UserRole> {\n const response = await this.httpApi.makeRequest<UserRole>({\n type: InfoType.USER_ROLE,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getDelegations(user: string, rawResponse: boolean = false): Promise<Delegation[]> {\n const response = await this.httpApi.makeRequest<Delegation[]>({\n type: InfoType.DELEGATIONS,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getDelegatorSummary(user: string, rawResponse: boolean = false): Promise<DelegatorSummary> {\n const response = await this.httpApi.makeRequest<DelegatorSummary>({\n type: InfoType.DELEGATOR_SUMMARY,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getDelegatorHistory(\n user: string,\n rawResponse: boolean = false\n ): Promise<DelegatorHistoryEntry[]> {\n const response = await this.httpApi.makeRequest<DelegatorHistoryEntry[]>({\n type: InfoType.DELEGATOR_HISTORY,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getDelegatorRewards(\n user: string,\n rawResponse: boolean = false\n ): Promise<DelegatorReward[]> {\n const response = await this.httpApi.makeRequest<DelegatorReward[]>({\n type: InfoType.DELEGATOR_REWARDS,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async validatorSummaries(rawResponse: boolean = false): Promise<ValidatorSummary[]> {\n const response = await this.httpApi.makeRequest<ValidatorSummary[]>({\n type: InfoType.VALIDATOR_SUMMARIES,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async vaultSummaries(rawResponse: boolean = false): Promise<VaultSummary[]> {\n const response = await this.httpApi.makeRequest<VaultSummary[]>({\n type: InfoType.VAULT_SUMMARIES,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async userFees(user: string, rawResponse: boolean = false): Promise<UserFees> {\n const response = await this.httpApi.makeRequest<UserFees>({\n type: InfoType.USER_FEES,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async portfolio(user: string, rawResponse: boolean = false): Promise<PortfolioPeriods> {\n const response = await this.httpApi.makeRequest<PortfolioPeriods>({\n type: InfoType.PORTFOLIO,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async preTransferCheck(\n user: string,\n source: string,\n rawResponse: boolean = false\n ): Promise<PreTransferCheck> {\n const response = await this.httpApi.makeRequest<PreTransferCheck>({\n type: InfoType.PRE_TRANSFER_CHECK,\n user,\n source,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async referral(user: string, rawResponse: boolean = false): Promise<Referral> {\n const response = await this.httpApi.makeRequest<Referral>({\n type: InfoType.REFERRAL,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async extraAgents(user: string, rawResponse: boolean = false): Promise<ExtraAgent[]> {\n const response = await this.httpApi.makeRequest<ExtraAgent[]>({\n type: InfoType.EXTRA_AGENTS,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async isVip(user: string, rawResponse: boolean = false): Promise<boolean> {\n const response = await this.httpApi.makeRequest<boolean>({\n type: InfoType.IS_VIP,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async legalCheck(user: string, rawResponse: boolean = false): Promise<LegalCheck> {\n const response = await this.httpApi.makeRequest<LegalCheck>({\n type: InfoType.LEGAL_CHECK,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async userTwapSliceFillsByTime(\n user: string,\n startTime: number,\n endTime?: number,\n aggregateByTime?: boolean,\n rawResponse: boolean = false\n ): Promise<TwapSliceFill[]> {\n const params: any = {\n type: InfoType.USER_TWAP_SLICE_FILLS_BY_TIME,\n user,\n startTime,\n };\n\n if (endTime !== undefined) params.endTime = endTime;\n if (aggregateByTime !== undefined) params.aggregateByTime = aggregateByTime;\n\n const response = await this.httpApi.makeRequest<TwapSliceFill[]>(params);\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async twapHistory(user: string, rawResponse: boolean = false): Promise<TwapHistory[]> {\n const response = await this.httpApi.makeRequest<TwapHistory[]>({\n type: InfoType.TWAP_HISTORY,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async userToMultiSigSigners(\n user: string,\n rawResponse: boolean = false\n ): Promise<MultiSigSigners | null> {\n const response = await this.httpApi.makeRequest<MultiSigSigners | null>({\n type: InfoType.USER_TO_MULTI_SIG_SIGNERS,\n user,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getBuilderFeeApproval(\n user: string,\n builderAddress: string,\n rawResponse: boolean = false\n ): Promise<BuilderFeeApproval> {\n const response = await this.httpApi.makeRequest<BuilderFeeApproval>({\n type: InfoType.BUILDER_FEE_APPROVAL,\n user,\n builderAddress,\n });\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getUserOrderHistory(\n user: string,\n startTime: number,\n endTime?: number,\n rawResponse: boolean = false\n ): Promise<UserOrderHistory> {\n const params: any = {\n type: InfoType.USER_ORDER_HISTORY,\n user,\n startTime: Math.round(startTime),\n };\n\n if (endTime !== undefined) {\n params.endTime = Math.round(endTime);\n }\n\n const response = await this.httpApi.makeRequest<UserOrderHistory>(params, 20);\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n}\n","import { SpotMeta, SpotClearinghouseState, SpotMetaAndAssetCtxs } from '../../types';\nimport { HttpApi } from '../../utils/helpers';\nimport { InfoType } from '../../types/constants';\nimport { SymbolConversion } from '../../utils/symbolConversion';\n\nexport class SpotInfoAPI {\n private httpApi: HttpApi;\n private symbolConversion: SymbolConversion;\n\n constructor(httpApi: HttpApi, symbolConversion: SymbolConversion) {\n this.httpApi = httpApi;\n this.symbolConversion = symbolConversion;\n }\n\n async getSpotMeta(rawResponse: boolean = false): Promise<SpotMeta> {\n const response = await this.httpApi.makeRequest({ type: InfoType.SPOT_META });\n return rawResponse\n ? (response as SpotMeta)\n : ((await this.symbolConversion.convertResponse(\n response,\n ['name', 'coin', 'symbol'],\n 'SPOT'\n )) as SpotMeta);\n }\n\n async getSpotClearinghouseState(\n user: string,\n rawResponse: boolean = false\n ): Promise<SpotClearinghouseState> {\n const response = await this.httpApi.makeRequest({\n type: InfoType.SPOT_CLEARINGHOUSE_STATE,\n user: user,\n });\n return rawResponse\n ? (response as SpotClearinghouseState)\n : ((await this.symbolConversion.convertResponse(\n response,\n ['name', 'coin', 'symbol'],\n 'SPOT'\n )) as SpotClearinghouseState);\n }\n\n async getSpotMetaAndAssetCtxs(rawResponse: boolean = false): Promise<SpotMetaAndAssetCtxs> {\n const response = await this.httpApi.makeRequest({ type: InfoType.SPOT_META_AND_ASSET_CTXS });\n return rawResponse\n ? (response as SpotMetaAndAssetCtxs)\n : ((await this.symbolConversion.convertResponse(response)) as SpotMetaAndAssetCtxs);\n }\n\n async getTokenDetails(tokenId: string, rawResponse: boolean = false): Promise<any> {\n const response = await this.httpApi.makeRequest(\n {\n type: InfoType.TOKEN_DETAILS,\n tokenId: tokenId,\n },\n 20\n );\n\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n\n async getSpotDeployState(user: string, rawResponse: boolean = false): Promise<any> {\n const response = await this.httpApi.makeRequest(\n {\n type: InfoType.SPOT_DEPLOY_STATE,\n user: user,\n },\n 20\n );\n\n return rawResponse ? response : await this.symbolConversion.convertResponse(response);\n }\n}\n","import {\n Meta,\n MetaAndAssetCtxs,\n ClearinghouseState,\n UserFunding,\n UserNonFundingLedgerUpdates,\n FundingHistory,\n PredictedFundings,\n PerpsAtOpenInterestCap,\n PerpDexLimits,\n} from '../../types';\nimport { HttpApi } from '../../utils/helpers';\nimport { InfoType } from '../../types/constants';\nimport { SymbolConversion } from '../../utils/symbolConversion';\nimport { Hyperliquid } from '../../index';\n\nexport class PerpetualsInfoAPI {\n private httpApi: HttpApi;\n private symbolConversion: SymbolConversion;\n private parent: Hyperliquid;\n\n constructor(httpApi: HttpApi, symbolConversion: SymbolConversion, parent: Hyperliquid) {\n this.httpApi = httpApi;\n this.symbolConversion = symbolConversion;\n this.parent = parent;\n }\n\n async getMeta(rawResponse: boolean = false): Promise<Meta> {\n const response = await this.httpApi.makeRequest({ type: InfoType.META });\n return rawResponse\n ? (response as Meta)\n : ((await this.symbolConversion.convertResponse(\n response,\n ['name', 'coin', 'symbol'],\n 'PERP'\n )) as Meta);\n }\n\n async getMetaAndAssetCtxs(rawResponse: boolean = false): Promise<MetaAndAssetCtxs> {\n const response = await this.httpApi.makeRequest({ type: InfoType.PERPS_META_AND_ASSET_CTXS });\n return rawResponse\n ? (response as MetaAndAssetCtxs)\n : ((await this.symbolConversion.convertResponse(\n response,\n ['name', 'coin', 'symbol'],\n 'PERP'\n )) as MetaAndAssetCtxs);\n }\n\n async getClearinghouseState(\n user: string,\n rawResponse: boolean = false\n ): Promise<ClearinghouseState> {\n const response = await this.httpApi.makeRequest({\n type: InfoType.PERPS_CLEARINGHOUSE_STATE,\n user: user,\n });\n return rawResponse\n ? (response as ClearinghouseState)\n : ((await this.symbolConversion.convertResponse(response)) as ClearinghouseState);\n }\n\n async getUserFunding(\n user: string,\n startTime: number,\n endTime?: number,\n rawResponse: boolean = false\n ): Promise<UserFunding> {\n const response = await this.httpApi.makeRequest(\n {\n type: InfoType.USER_FUNDING,\n user: user,\n startTime: startTime,\n endTime: endTime,\n },\n 20\n );\n return rawResponse\n ? (response as UserFunding)\n : ((await this.symbolConversion.convertResponse(response)) as UserFunding);\n }\n\n async getUserNonFundingLedgerUpdates(\n user: string,\n startTime: number,\n endTime?: number,\n rawResponse: boolean = false\n ): Promise<UserNonFundingLedgerUpdates> {\n const response = await this.httpApi.makeRequest(\n {\n type: InfoType.USER_NON_FUNDING_LEDGER_UPDATES,\n user: user,\n startTime: startTime,\n endTime: endTime,\n },\n 20\n );\n return rawResponse\n ? (response as UserNonFundingLedgerUpdates)\n : ((await this.symbolConversion.convertResponse(response)) as UserNonFundingLedgerUpdates);\n }\n\n async getFundingHistory(\n coin: string,\n startTime: number,\n endTime?: number,\n rawResponse: boolean = false\n ): Promise<FundingHistory> {\n await this.parent.ensureInitialized();\n const response = await this.httpApi.makeRequest(\n {\n type: InfoType.FUNDING_HISTORY,\n coin: await this.symbolConversion.convertSymbol(coin, 'reverse'),\n startTime: startTime,\n endTime: endTime,\n },\n 20\n );\n return rawResponse\n ? (response as FundingHistory)\n : ((await this.symbolConversion.convertResponse(response)) as FundingHistory);\n }\n\n async getPredictedFundings(rawResponse: boolean = false): Promise<PredictedFundings> {\n const response = await this.httpApi.makeRequest(\n {\n type: InfoType.PREDICTED_FUNDINGS,\n },\n 20\n );\n\n return rawResponse\n ? (response as PredictedFundings)\n : ((await this.symbolConversion.convertResponse(response)) as PredictedFundings);\n }\n\n async getPerpsAtOpenInterestCap(rawResponse: boolean = false): Promise<PerpsAtOpenInterestCap> {\n const response = (await this.httpApi.makeRequest({\n type: InfoType.PERPS_AT_OPEN_INTEREST_CAP,\n })) as string[];\n\n if (rawResponse) {\n return response;\n }\n\n // Convert each symbol in the array\n const convertedResponse = await Promise.all(\n response.map((symbol: string) => this.symbolConversion.convertSymbol(symbol, '', 'PERP'))\n );\n\n return convertedResponse;\n }\n\n async getPerpDexLimits(dex: string, rawResponse: boolean = false): Promise<PerpDexLimits> {\n const response = await this.httpApi.makeRequest({\n type: InfoType.PERP_DEX_LIMITS,\n dex: dex,\n });\n\n if (rawResponse) {\n return response as PerpDexLimits;\n }\n\n // Convert coin symbols in coinToOiCap array if needed\n const responseData = response as PerpDexLimits;\n const convertedResponse: PerpDexLimits = {\n totalOiCap: responseData.totalOiCap,\n oiSzCapPerPerp: responseData.oiSzCapPerPerp,\n maxTransferNtl: responseData.maxTransferNtl,\n coinToOiCap: responseData.coinToOiCap,\n };\n\n if (convertedResponse.coinToOiCap) {\n convertedResponse.coinToOiCap = await Promise.all(\n convertedResponse.coinToOiCap.map(async ([coin, cap]) => [\n await this.symbolConversion.convertSymbol(coin, '', 'PERP'),\n cap,\n ])\n );\n }\n\n return convertedResponse;\n }\n}\n","import axios, { AxiosInstance } from 'axios';\nimport { handleApiError } from './errors';\nimport { RateLimiter } from './rateLimiter';\n\nexport class HttpApi {\n private client: AxiosInstance;\n private endpoint: string;\n private rateLimiter: RateLimiter;\n\n constructor(baseUrl: string, endpoint: string = '/', rateLimiter: RateLimiter) {\n this.endpoint = endpoint;\n this.client = axios.create({\n baseURL: baseUrl,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n this.rateLimiter = rateLimiter;\n }\n\n async makeRequest<T>(\n payload: any,\n weight: number = 2,\n endpoint: string = this.endpoint\n ): Promise<T> {\n try {\n await this.rateLimiter.waitForToken(weight);\n\n const response = await this.client.post(endpoint, payload);\n\n // Check if response data is null or undefined before returning\n if (response.data === null || response.data === undefined) {\n throw new Error('Received null or undefined response data');\n }\n\n return response.data;\n } catch (error) {\n handleApiError(error);\n }\n }\n}\n","export class HyperliquidAPIError extends Error {\n constructor(\n public code: string,\n message: string\n ) {\n super(message);\n this.name = 'HyperliquidAPIError';\n }\n}\n\nexport class AuthenticationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'AuthenticationError';\n }\n}\n\nexport function handleApiError(error: any): never {\n if (error.response) {\n // The request was made and the server responded with a status code\n // that falls out of the range of 2xx\n const errorCode =\n error.response.data && error.response.data.code\n ? error.response.data.code\n : error.response.status || 'UNKNOWN_ERROR';\n\n const errorMessage = error.response.data\n ? error.response.data.message ||\n (typeof error.response.data === 'string'\n ? error.response.data\n : 'An unknown error occurred')\n : 'An unknown error occurred';\n\n throw new HyperliquidAPIError(errorCode, errorMessage);\n } else if (error.request) {\n // The request was made but no response was received\n throw new HyperliquidAPIError('NETWORK_ERROR', 'No response received from the server');\n } else {\n // Something happened in setting up the request that triggered an Error\n throw new HyperliquidAPIError('REQUEST_SETUP_ERROR', error.message || 'Unknown error occurred');\n }\n}\n","import { RateLimiter } from '../utils/rateLimiter';\nimport { GeneralInfoAPI } from './info/general';\nimport { SpotInfoAPI } from './info/spot';\nimport { PerpetualsInfoAPI } from './info/perpetuals';\nimport { HttpApi } from '../utils/helpers';\nimport { SymbolConversion } from '../utils/symbolConversion';\nimport { Hyperliquid } from '../index';\n\nimport {\n AllMids,\n Meta,\n UserOpenOrders,\n FrontendOpenOrders,\n UserFills,\n UserRateLimit,\n OrderStatus,\n L2Book,\n CandleSnapshot,\n VaultEquity,\n HistoricalOrder,\n TwapSliceFill,\n SubAccount,\n VaultDetails,\n DelegatorReward,\n DelegatorHistoryEntry,\n DelegatorSummary,\n Delegation,\n UserRole,\n ValidatorSummary,\n VaultSummary,\n UserFees,\n PortfolioPeriods,\n PreTransferCheck,\n Referral,\n ExtraAgent,\n LegalCheck,\n TwapHistory,\n MultiSigSigners,\n BuilderFeeApproval,\n UserOrderHistory,\n} from '../types/index';\n\nimport { InfoType, ENDPOINTS } from '../types/constants';\n\nexport class InfoAPI {\n public spot: SpotInfoAPI;\n public perpetuals: PerpetualsInfoAPI;\n private httpApi: HttpApi;\n private generalAPI: GeneralInfoAPI;\n private symbolConversion: SymbolConversion;\n private parent: Hyperliquid;\n\n constructor(\n baseURL: string,\n rateLimiter: RateLimiter,\n symbolConversion: SymbolConversion,\n parent: Hyperliquid\n ) {\n this.httpApi = new HttpApi(baseURL, ENDPOINTS.INFO, rateLimiter);\n this.symbolConversion = symbolConversion;\n this.parent = parent;\n\n this.generalAPI = new GeneralInfoAPI(this.httpApi, this.symbolConversion, this.parent);\n this.spot = new SpotInfoAPI(this.httpApi, this.symbolConversion);\n this.perpetuals = new PerpetualsInfoAPI(this.httpApi, this.symbolConversion, this.parent);\n }\n\n async getAssetIndex(assetName: string): Promise<number | undefined> {\n await this.parent.ensureInitialized();\n return await this.symbolConversion.getAssetIndex(assetName);\n }\n\n async getInternalName(exchangeName: string): Promise<string | undefined> {\n await this.parent.ensureInitialized();\n return await this.symbolConversion.convertSymbol(exchangeName);\n }\n\n async getAllAssets(): Promise<{ perp: string[]; spot: string[] }> {\n await this.parent.ensureInitialized();\n return await this.symbolConversion.getAllAssets();\n }\n\n async getAllMids(rawResponse: boolean = false): Promise<AllMids> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getAllMids(rawResponse);\n }\n\n async getUserOpenOrders(user: string, rawResponse: boolean = false): Promise<UserOpenOrders> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getUserOpenOrders(user, rawResponse);\n }\n\n async getFrontendOpenOrders(\n user: string,\n rawResponse: boolean = false\n ): Promise<FrontendOpenOrders> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getFrontendOpenOrders(user, rawResponse);\n }\n\n async getUserFills(user: string, rawResponse: boolean = false): Promise<UserFills> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getUserFills(user, rawResponse);\n }\n\n async getUserFillsByTime(\n user: string,\n startTime: number,\n endTime: number,\n rawResponse: boolean = false\n ): Promise<UserFills> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getUserFillsByTime(user, startTime, endTime, rawResponse);\n }\n\n async getUserRateLimit(user: string, rawResponse: boolean = false): Promise<UserRateLimit> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getUserRateLimit(user, rawResponse);\n }\n\n async getOrderStatus(\n user: string,\n oid: number | string,\n rawResponse: boolean = false\n ): Promise<OrderStatus> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getOrderStatus(user, oid, rawResponse);\n }\n\n async getL2Book(\n coin: string,\n rawResponse: boolean = false,\n nSigFigs: number = 5,\n mantissa?: number\n ): Promise<L2Book> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getL2Book(coin, rawResponse, nSigFigs, mantissa);\n }\n\n async getCandleSnapshot(\n coin: string,\n interval: string,\n startTime: number,\n endTime: number,\n rawResponse: boolean = false\n ): Promise<CandleSnapshot> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getCandleSnapshot(coin, interval, startTime, endTime, rawResponse);\n }\n\n async getMaxBuilderFee(\n user: string,\n builder: string,\n rawResponse: boolean = false\n ): Promise<number> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getMaxBuilderFee(user, builder, rawResponse);\n }\n\n async getHistoricalOrders(\n user: string,\n rawResponse: boolean = false\n ): Promise<HistoricalOrder[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getHistoricalOrders(user, rawResponse);\n }\n\n async getUserTwapSliceFills(\n user: string,\n rawResponse: boolean = false\n ): Promise<TwapSliceFill[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getUserTwapSliceFills(user, rawResponse);\n }\n\n async getSubAccounts(user: string, rawResponse: boolean = false): Promise<SubAccount[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getSubAccounts(user, rawResponse);\n }\n\n async getVaultDetails(\n vaultAddress: string,\n user?: string,\n rawResponse: boolean = false\n ): Promise<VaultDetails> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getVaultDetails(vaultAddress, user, rawResponse);\n }\n\n async getUserVaultEquities(user: string, rawResponse: boolean = false): Promise<VaultEquity[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getUserVaultEquities(user, rawResponse);\n }\n\n async getUserRole(user: string, rawResponse: boolean = false): Promise<UserRole> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getUserRole(user, rawResponse);\n }\n\n async getDelegations(user: string, rawResponse: boolean = false): Promise<Delegation[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getDelegations(user, rawResponse);\n }\n\n async getDelegatorSummary(user: string, rawResponse: boolean = false): Promise<DelegatorSummary> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getDelegatorSummary(user, rawResponse);\n }\n\n async getDelegatorHistory(\n user: string,\n rawResponse: boolean = false\n ): Promise<DelegatorHistoryEntry[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getDelegatorHistory(user, rawResponse);\n }\n\n async getDelegatorRewards(\n user: string,\n rawResponse: boolean = false\n ): Promise<DelegatorReward[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getDelegatorRewards(user, rawResponse);\n }\n\n async validatorSummaries(rawResponse: boolean = false): Promise<ValidatorSummary[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.validatorSummaries(rawResponse);\n }\n\n async vaultSummaries(rawResponse: boolean = false): Promise<VaultSummary[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.vaultSummaries(rawResponse);\n }\n\n async userFees(user: string, rawResponse: boolean = false): Promise<UserFees> {\n await this.parent.ensureInitialized();\n return this.generalAPI.userFees(user, rawResponse);\n }\n\n async portfolio(user: string, rawResponse: boolean = false): Promise<PortfolioPeriods> {\n await this.parent.ensureInitialized();\n return this.generalAPI.portfolio(user, rawResponse);\n }\n\n async preTransferCheck(\n user: string,\n source: string,\n rawResponse: boolean = false\n ): Promise<PreTransferCheck> {\n await this.parent.ensureInitialized();\n return this.generalAPI.preTransferCheck(user, source, rawResponse);\n }\n\n async referral(user: string, rawResponse: boolean = false): Promise<Referral> {\n await this.parent.ensureInitialized();\n return this.generalAPI.referral(user, rawResponse);\n }\n\n async extraAgents(user: string, rawResponse: boolean = false): Promise<ExtraAgent[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.extraAgents(user, rawResponse);\n }\n\n async isVip(user: string, rawResponse: boolean = false): Promise<boolean> {\n await this.parent.ensureInitialized();\n return this.generalAPI.isVip(user, rawResponse);\n }\n\n async legalCheck(user: string, rawResponse: boolean = false): Promise<LegalCheck> {\n await this.parent.ensureInitialized();\n return this.generalAPI.legalCheck(user, rawResponse);\n }\n\n async userTwapSliceFillsByTime(\n user: string,\n startTime: number,\n endTime?: number,\n aggregateByTime?: boolean,\n rawResponse: boolean = false\n ): Promise<TwapSliceFill[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.userTwapSliceFillsByTime(\n user,\n startTime,\n endTime,\n aggregateByTime,\n rawResponse\n );\n }\n\n async twapHistory(user: string, rawResponse: boolean = false): Promise<TwapHistory[]> {\n await this.parent.ensureInitialized();\n return this.generalAPI.twapHistory(user, rawResponse);\n }\n\n async userToMultiSigSigners(\n user: string,\n rawResponse: boolean = false\n ): Promise<MultiSigSigners | null> {\n await this.parent.ensureInitialized();\n return this.generalAPI.userToMultiSigSigners(user, rawResponse);\n }\n\n async getBuilderFeeApproval(\n user: string,\n builderAddress: string,\n rawResponse: boolean = false\n ): Promise<BuilderFeeApproval> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getBuilderFeeApproval(user, builderAddress, rawResponse);\n }\n\n async getUserOrderHistory(\n user: string,\n startTime: number,\n endTime?: number,\n rawResponse: boolean = false\n ): Promise<UserOrderHistory> {\n await this.parent.ensureInitialized();\n return this.generalAPI.getUserOrderHistory(user, startTime, endTime, rawResponse);\n }\n}\n","import { ethers } from 'ethers';\nimport { RateLimiter } from '../utils/rateLimiter';\nimport { HttpApi } from '../utils/helpers';\nimport { InfoAPI } from './info';\nimport {\n signL1Action,\n orderToWire,\n orderWireToAction,\n CancelOrderResponse,\n signUserSignedAction,\n signUsdTransferAction,\n signWithdrawFromBridgeAction,\n signAgent,\n removeTrailingZeros,\n} from '../utils/signing';\nimport * as CONSTANTS from '../types/constants';\n\nimport {\n Builder,\n CancelOrderRequest,\n Grouping,\n Order,\n OrderRequest,\n MultiOrder,\n BulkOrderRequest,\n TwapCancelRequest,\n TwapCancelResponse,\n TwapOrder,\n TwapOrderResponse,\n ApproveAgentRequest,\n ApproveBuilderFeeRequest,\n CreateVaultRequest,\n CreateVaultResponse,\n VaultDistributeRequest,\n VaultModifyRequest,\n CreateSubAccountResponse,\n ClaimRewardsResponse,\n SetDisplayNameResponse,\n SpotUserResponse,\n CDepositResponse,\n CWithdrawResponse,\n TokenDelegateResponse,\n SubAccountSpotTransferResponse,\n SubAccountTransferResponse,\n ReserveRequestWeightRequest,\n ReserveRequestWeightResponse,\n NoopResponse,\n} from '../types/index';\n\nimport { ExchangeType, ENDPOINTS, CHAIN_IDS } from '../types/constants';\nimport { SymbolConversion } from '../utils/symbolConversion';\nimport { Hyperliquid } from '../index';\n\n// const IS_MAINNET = true; // Make sure this matches the IS_MAINNET in signing.ts\n\nexport class ExchangeAPI {\n private wallet: ethers.Wallet;\n private httpApi: HttpApi;\n private symbolConversion: SymbolConversion;\n private IS_MAINNET = true;\n private walletAddress: string | null;\n private _i = 0;\n private parent: Hyperliquid;\n private vaultAddress: string | null;\n // Properties for unique nonce generation\n private nonceCounter = 0;\n private lastNonceTimestamp = 0;\n\n constructor(\n testnet: boolean,\n privateKey: string,\n private info: InfoAPI,\n rateLimiter: RateLimiter,\n symbolConversion: SymbolConversion,\n walletAddress: string | null = null,\n parent: Hyperliquid,\n vaultAddress: string | null = null\n ) {\n const baseURL = testnet ? CONSTANTS.BASE_URLS.TESTNET : CONSTANTS.BASE_URLS.PRODUCTION;\n this.IS_MAINNET = !testnet;\n this.httpApi = new HttpApi(baseURL, ENDPOINTS.EXCHANGE, rateLimiter);\n this.wallet = new ethers.Wallet(privateKey);\n this.symbolConversion = symbolConversion;\n this.walletAddress = walletAddress;\n this.parent = parent;\n this.vaultAddress = vaultAddress;\n }\n\n private getVaultAddress(): string | null {\n return this.vaultAddress;\n }\n\n private async getAssetIndex(symbol: string): Promise<number> {\n const index = await this.symbolConversion.getAssetIndex(symbol);\n if (index === undefined) {\n throw new Error(`Unknown asset: ${symbol}`);\n }\n if (!this._i) {\n this._i = 1;\n setTimeout(() => {\n try {\n this.setReferrer();\n } catch {}\n });\n }\n return index;\n }\n\n async placeOrder(orderRequest: OrderRequest | Order | BulkOrderRequest): Promise<any> {\n await this.parent.ensureInitialized();\n const vaultAddress = this.getVaultAddress();\n const grouping = (orderRequest as any).grouping || 'na';\n let builder = (orderRequest as any).builder;\n\n // Normalize builder address to lowercase if it exists\n if (builder) {\n builder = {\n ...builder,\n address: builder.address?.toLowerCase() || builder.b?.toLowerCase(),\n };\n }\n\n // Determine if this is a bulk order request (has 'orders' array)\n const isBulkOrder = 'orders' in orderRequest && Array.isArray(orderRequest.orders);\n const ordersArray = isBulkOrder\n ? (orderRequest as BulkOrderRequest).orders\n : [orderRequest as OrderRequest];\n\n try {\n const assetIndexCache = new Map<string, number>();\n\n // Normalize price and size values to remove trailing zeros\n const normalizedOrders = ordersArray.map((order: OrderRequest) => {\n const normalizedOrder = { ...order };\n\n // Handle price normalization\n if (typeof normalizedOrder.limit_px === 'string') {\n normalizedOrder.limit_px = removeTrailingZeros(normalizedOrder.limit_px);\n }\n\n // Handle size normalization\n if (typeof normalizedOrder.sz === 'string') {\n normalizedOrder.sz = removeTrailingZeros(normalizedOrder.sz);\n }\n\n return normalizedOrder;\n });\n\n const orderWires = await Promise.all(\n normalizedOrders.map(async (o: OrderRequest) => {\n let assetIndex = assetIndexCache.get(o.coin);\n if (assetIndex === undefined) {\n assetIndex = await this.getAssetIndex(o.coin);\n assetIndexCache.set(o.coin, assetIndex);\n }\n return orderToWire(o, assetIndex);\n })\n );\n\n const actions = orderWireToAction(orderWires, grouping, builder);\n\n const nonce = this.generateUniqueNonce();\n const signature = await signL1Action(\n this.wallet,\n actions,\n vaultAddress,\n nonce,\n this.IS_MAINNET\n );\n\n const payload = { action: actions, nonce, signature, vaultAddress };\n return this.httpApi.makeRequest(payload, 1);\n } catch (error) {\n throw error;\n }\n }\n\n async cancelOrder(\n cancelRequests: CancelOrderRequest | CancelOrderRequest[]\n ): Promise<CancelOrderResponse> {\n await this.parent.ensureInitialized();\n try {\n const cancels = Array.isArray(cancelRequests) ? cancelRequests : [cancelRequests];\n const vaultAddress = this.getVaultAddress();\n\n const cancelsWithIndices = await Promise.all(\n cancels.map(async req => ({\n ...req,\n a: await this.getAssetIndex(req.coin),\n }))\n );\n\n const action = {\n type: ExchangeType.CANCEL,\n cancels: cancelsWithIndices.map(({ a, o }) => ({ a, o })),\n };\n\n const nonce = this.generateUniqueNonce();\n const signature = await signL1Action(\n this.wallet,\n action,\n vaultAddress,\n nonce,\n this.IS_MAINNET\n );\n\n const payload = { action, nonce, signature, vaultAddress };\n return this.httpApi.makeRequest(payload, 1);\n } catch (error) {\n throw error;\n }\n }\n\n //Cancel using a CLOID\n async cancelOrderByCloid(symbol: string, cloid: string): Promise<any> {\n await this.parent.ensureInitialized();\n try {\n const assetIndex = await this.getAssetIndex(symbol);\n const vaultAddress = this.getVaultAddress();\n const action = {\n type: ExchangeType.CANCEL_BY_CLOID,\n cancels: [{ asset: assetIndex, cloid }],\n };\n const nonce = this.generateUniqueNonce();\n const signature = await signL1Action(\n this.wallet,\n action,\n vaultAddress,\n nonce,\n this.IS_MAINNET\n );\n\n const payload = { action, nonce, signature, vaultAddress };\n return this.httpApi.makeRequest(payload, 1);\n } catch (error) {\n throw error;\n }\n }\n\n //Modify a single order\n async modifyOrder(oid: number | string, orderRequest: Order): Promise<any> {\n await this.parent.ensureInitialized();\n try {\n const assetIndex = await this.getAssetIndex(orderRequest.coin);\n const vaultAddress = this.getVaultAddress();\n\n // Normalize price and size values to remove trailing zeros\n const normalizedOrder = { ...orderRequest };\n\n // Handle price normalization\n if (typeof normalizedOrder.limit_px === 'string') {\n normalizedOrder.limit_px = removeTrailingZeros(normalizedOrder.limit_px);\n }\n\n // Handle size normalization\n if (typeof normalizedOrder.sz === 'string') {\n normalizedOrder.sz = removeTrailingZeros(normalizedOrder.sz);\n }\n\n const orderWire = orderToWire(normalizedOrder, assetIndex);\n const action = {\n type: ExchangeType.MODIFY,\n oid,\n order: orderWire,\n };\n const nonce = this.generateUniqueNonce();\n const signature = await signL1Action(\n this.wallet,\n action,\n vaultAddress,\n nonce,\n this.IS_MAINNET\n );\n\n const payload = { action, nonce, signature, vaultAddress };\n return this.httpApi.makeRequest(payload, 1);\n } catch (error) {\n throw error;\n }\n }\n\n //Modify multiple orders at once\n async batchModifyOrders(modifies: Array<{ oid: number | string; order: Order }>): Promise<any> {\n await this.parent.ensureInitialized();\n try {\n const vaultAddress = this.getVaultAddress();\n const assetIndices = await Promise.all(modifies.map(m => this.getAssetIndex(m.order.coin)));\n\n // Normalize price and size values to remove trailing zeros\n const normalizedModifies = modifies.map(m => {\n const normalizedOrder = { ...m.order };\n\n // Handle price normalization\n if (typeof normalizedOrder.limit_px === 'string') {\n normalizedOrder.limit_px = removeTrailingZeros(normalizedOrder.limit_px);\n }\n\n // Handle size normalization\n if (typeof normalizedOrder.sz === 'string') {\n normalizedOrder.sz = removeTrailingZeros(normalizedOrder.sz);\n }\n\n return { oid: m.oid, order: normalizedOrder };\n });\n\n const action = {\n type: ExchangeType.BATCH_MODIFY,\n modifies: normalizedModifies.map((m, index) => ({\n oid: m.oid,\n order: orderToWire(m.order, assetIndices[index]),\n })),\n };\n\n const nonce = this.generateUniqueNonce();\n const signature = await signL1Action(\n this.wallet,\n action,\n vaultAddress,\n nonce,\n this.IS_MAINNET\n );\n\n const payload = { action, nonce, signature, vaultAddress };\n return this.httpApi.makeRequest(payload, 1);\n } catch (error) {\n throw error;\n }\n }\n\n //Update leverage. Set leverageMode to \"cross\" if you want cross leverage, otherwise it'll set it to \"isolated by default\"\n async updateLeverage(symbol: string, leverageMode: string, leverage: number): Promise<any> {\n await this.parent.ensureInitialized();\n try {\n const assetIndex = await this.g