UNPKG

@desk-exchange/typescript-sdk

Version:
1,157 lines (1,143 loc) 31.5 kB
// src/api/auth.ts import { randomBytes } from "crypto"; import { ethers } from "ethers"; import axios from "axios"; // src/types/constants.ts var BASE_URLS = { mainnet: "https://api.happytrading.global", testnet: "https://stg-trade-api.happytrading.global" }; var CRM_URLS = { mainnet: "https://api.desk.exchange", testnet: "https://dev-api.desk.exchange" }; var WSS_URLS = { mainnet: "wss://ws-api.happytrading.global/ws", testnet: "wss://stg-trade-ws-api.happytrading.global/ws" }; var CHAIN_ID = { mainnet: 8453, testnet: 421614, base: 8453, arbitrumSepolia: 421614 }; var VAULT_ADDRESS = { mainnet: "0x764ab030159466edf9663e3fe3198c5d5c26c122", testnet: "0x6e664f5025ee54704040a970d2bfa1ecbbc20fd4", [CHAIN_ID.base]: "0x764ab030159466edf9663e3fe3198c5d5c26c122", [CHAIN_ID.arbitrumSepolia]: "0x6e664f5025ee54704040a970d2bfa1ecbbc20fd4" }; var BROKER_ID = "DESK-SDK"; // src/api/auth.ts var Auth = class { wallet; subAccountId; authenticated; client; crmClient; network; provider; constructor(network, privateKey = process.env.PRIVATE_KEY, subAccountId) { this.provider = new ethers.JsonRpcProvider( "https://arbitrum-sepolia-rpc.publicnode.com" ); this.wallet = privateKey ? new ethers.Wallet(privateKey, this.provider) : void 0; this.subAccountId = subAccountId; this.network = network; this.client = axios.create({ baseURL: BASE_URLS[network], headers: { "Content-Type": "application/json" } }); this.crmClient = axios.create({ baseURL: CRM_URLS[network], headers: { "Content-Type": "application/json" } }); this.authenticated = false; } generateNonce() { const expiredAt = BigInt(Date.now() + 1e3 * 60) * BigInt(1 << 20); const random = parseInt(randomBytes(3).toString("hex"), 16) % (1 << 20); return (expiredAt + BigInt(random)).toString(); } async generateJwt() { if (!this.wallet) return; const nonce = this.generateNonce(); const message = `Welcome to DESK! Please sign this message to verify ownership of your wallet and proceed. By signing, you confirm the following: you have read, understood, and agreed to the Terms & Conditions, Privacy Policy, and any other relevant terms and conditions announced by DESK. This request will not trigger a blockchain transaction or cost any gas fees. Wallet address: ${this.wallet.address?.toLowerCase()} Sub-account id: ${this.subAccountId.toString()} Nonce: ${nonce}`; const signature = await this.wallet.signMessage(message); const orderbookJwtResponse = await this.client.post(`/v2/auth/evm`, { account: this.wallet.address, subaccount_id: this.subAccountId.toString(), nonce, signature }); const crmJwtResponse = await this.crmClient.post(`/v1/users/auth`, { nonce, signature, subaccount_id: this.subAccountId.toString(), wallet_address: this.wallet.address }); if (orderbookJwtResponse.status === 200 && crmJwtResponse.status === 200) { this.client.defaults.headers.common["Authorization"] = `Bearer ${orderbookJwtResponse.data.data.jwt}`; this.crmClient.defaults.headers.common["Authorization"] = `Bearer ${crmJwtResponse.data.data.jwt}`; this.authenticated = true; } else { throw new Error("Could not generate JWT"); } } getSubaccount = () => { const subaccountIdHex = BigInt(this.subAccountId).toString(16).padStart(24, "0"); return this.wallet.address.concat(subaccountIdHex); }; isAuthenticated() { return this.authenticated; } }; // src/api/exchange.ts import { ethers as ethers2 } from "ethers"; // src/api/vault_abi.json var vault_abi_default = [ { type: "constructor", inputs: [], stateMutability: "nonpayable" }, { type: "receive", stateMutability: "payable" }, { type: "function", name: "WETH", inputs: [], outputs: [{ name: "", type: "address", internalType: "address" }], stateMutability: "view" }, { type: "function", name: "collateralIds", inputs: [ { name: "token", type: "address", internalType: "address" } ], outputs: [ { name: "collateralId", type: "address", internalType: "address" } ], stateMutability: "view" }, { type: "function", name: "deposit", inputs: [ { name: "_tokenAddress", type: "address", internalType: "address" }, { name: "_subaccount", type: "bytes32", internalType: "bytes32" }, { name: "_amount", type: "uint256", internalType: "uint256" } ], outputs: [ { name: "_requestId", type: "uint256", internalType: "uint256" } ], stateMutability: "payable" }, { type: "function", name: "depositRequests", inputs: [ { name: "requestId", type: "uint256", internalType: "uint256" } ], outputs: [ { name: "subaccount", type: "bytes32", internalType: "bytes32" }, { name: "amount", type: "uint256", internalType: "uint256" }, { name: "tokenAddress", type: "address", internalType: "address" } ], stateMutability: "view" }, { type: "function", name: "executeWithdrawal", inputs: [ { name: "_requestId", type: "uint256", internalType: "uint256" }, { name: "_transferAmount", type: "uint256", internalType: "uint256" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "initialize", inputs: [ { name: "_withdrawHandler", type: "address", internalType: "address" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "minDeposits", inputs: [ { name: "token", type: "address", internalType: "address" } ], outputs: [ { name: "minDepositAmount", type: "uint256", internalType: "uint256" } ], stateMutability: "view" }, { type: "function", name: "owner", inputs: [], outputs: [{ name: "", type: "address", internalType: "address" }], stateMutability: "view" }, { type: "function", name: "renounceOwnership", inputs: [], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "setCollateralId", inputs: [ { name: "_tokenAddress", type: "address", internalType: "address" }, { name: "_collateralId", type: "address", internalType: "address" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "setMinDeposit", inputs: [ { name: "_tokenAddress", type: "address", internalType: "address" }, { name: "_amount", type: "uint256", internalType: "uint256" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "setWETH", inputs: [ { name: "_weth", type: "address", internalType: "address" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "setWhitelist", inputs: [ { name: "_user", type: "address", internalType: "address" }, { name: "_isWhitelisted", type: "bool", internalType: "bool" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "setWithdrawableToken", inputs: [ { name: "_tokenAddress", type: "address", internalType: "address" }, { name: "_isWithdrawable", type: "bool", internalType: "bool" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "totalDepositRequests", inputs: [], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "totalWithdrawalRequests", inputs: [], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "transferOwnership", inputs: [ { name: "newOwner", type: "address", internalType: "address" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "whitelists", inputs: [ { name: "actor", type: "address", internalType: "address" } ], outputs: [ { name: "isWhitelisted", type: "bool", internalType: "bool" } ], stateMutability: "view" }, { type: "function", name: "withdraw", inputs: [ { name: "_tokenAddress", type: "address", internalType: "address" }, { name: "_subaccount", type: "bytes32", internalType: "bytes32" }, { name: "_amount", type: "uint256", internalType: "uint256" } ], outputs: [ { name: "_requestId", type: "uint256", internalType: "uint256" } ], stateMutability: "nonpayable" }, { type: "function", name: "withdrawHandler", inputs: [], outputs: [{ name: "", type: "address", internalType: "address" }], stateMutability: "view" }, { type: "function", name: "withdrawableTokens", inputs: [ { name: "token", type: "address", internalType: "address" } ], outputs: [{ name: "isAllow", type: "bool", internalType: "bool" }], stateMutability: "view" }, { type: "function", name: "withdrawalRequests", inputs: [ { name: "requestId", type: "uint256", internalType: "uint256" } ], outputs: [ { name: "subaccount", type: "bytes32", internalType: "bytes32" }, { name: "amount", type: "uint256", internalType: "uint256" }, { name: "tokenAddress", type: "address", internalType: "address" }, { name: "timestamp", type: "uint48", internalType: "uint48" }, { name: "isExecuted", type: "bool", internalType: "bool" } ], stateMutability: "view" }, { type: "event", name: "Initialized", inputs: [ { name: "version", type: "uint8", indexed: false, internalType: "uint8" } ], anonymous: false }, { type: "event", name: "LogDeposit", inputs: [ { name: "requestId", type: "uint256", indexed: true, internalType: "uint256" }, { name: "subaccount", type: "bytes32", indexed: false, internalType: "bytes32" }, { name: "tokenAddress", type: "address", indexed: false, internalType: "address" }, { name: "amount", type: "uint256", indexed: false, internalType: "uint256" } ], anonymous: false }, { type: "event", name: "LogSetAcceptedToken", inputs: [ { name: "tokenAddress", type: "address", indexed: true, internalType: "address" }, { name: "isAccepted", type: "bool", indexed: false, internalType: "bool" } ], anonymous: false }, { type: "event", name: "LogSetAssetService", inputs: [ { name: "oldAssetService", type: "address", indexed: true, internalType: "address" }, { name: "newAssetService", type: "address", indexed: false, internalType: "address" } ], anonymous: false }, { type: "event", name: "LogSetCollateralId", inputs: [ { name: "tokenAddress", type: "address", indexed: true, internalType: "address" }, { name: "collateralId", type: "address", indexed: true, internalType: "address" } ], anonymous: false }, { type: "event", name: "LogSetMinDeposit", inputs: [ { name: "tokenAddress", type: "address", indexed: true, internalType: "address" }, { name: "amount", type: "uint256", indexed: false, internalType: "uint256" } ], anonymous: false }, { type: "event", name: "LogSetWETH", inputs: [ { name: "weth", type: "address", indexed: true, internalType: "address" } ], anonymous: false }, { type: "event", name: "LogSetWhitelist", inputs: [ { name: "user", type: "address", indexed: true, internalType: "address" }, { name: "isWhitelisted", type: "bool", indexed: false, internalType: "bool" } ], anonymous: false }, { type: "event", name: "LogSetWithdrawableToken", inputs: [ { name: "tokenAddress", type: "address", indexed: true, internalType: "address" }, { name: "isWithdrawable", type: "bool", indexed: false, internalType: "bool" } ], anonymous: false }, { type: "event", name: "LogWithdrawal", inputs: [ { name: "requestId", type: "uint256", indexed: true, internalType: "uint256" }, { name: "subaccount", type: "bytes32", indexed: false, internalType: "bytes32" }, { name: "tokenAddress", type: "address", indexed: false, internalType: "address" }, { name: "amount", type: "uint256", indexed: false, internalType: "uint256" }, { name: "timestamp", type: "uint48", indexed: false, internalType: "uint48" } ], anonymous: false }, { type: "event", name: "LogWithdrawalProcessed", inputs: [ { name: "receiver", type: "address", indexed: true, internalType: "address" }, { name: "tokenAddress", type: "address", indexed: true, internalType: "address" }, { name: "amount", type: "uint256", indexed: false, internalType: "uint256" }, { name: "transferAmount", type: "uint256", indexed: false, internalType: "uint256" } ], anonymous: false }, { type: "event", name: "OwnershipTransferred", inputs: [ { name: "previousOwner", type: "address", indexed: true, internalType: "address" }, { name: "newOwner", type: "address", indexed: true, internalType: "address" } ], anonymous: false }, { type: "error", name: "Vault_AlreadyExecutedRequest", inputs: [] }, { type: "error", name: "Vault_ExceedWithdrawableAmount", inputs: [] }, { type: "error", name: "Vault_InvalidAddress", inputs: [] }, { type: "error", name: "Vault_InvalidAmount", inputs: [] }, { type: "error", name: "Vault_InvalidAuthentication", inputs: [] }, { type: "error", name: "Vault_InvalidRequest", inputs: [] }, { type: "error", name: "Vault_InvalidSubaccount", inputs: [] }, { type: "error", name: "Vault_InvalidWithdrawalToken", inputs: [] }, { type: "error", name: "Vault_LessThanMinimumDeposit", inputs: [] } ]; // src/api/exchange.ts var erc20ABI = [ "function approve(address spender, uint256 amount) returns (bool)", "function allowance(address owner, address spender) view returns (uint256)", "function decimals() view returns (uint8)", "function symbol() view returns (string)" ]; var Exchange = class { auth; parent; constructor(auth, parent) { this.auth = auth; this.parent = parent; } async depositCollateral(tokenAddress, amount) { if (!this.auth.wallet) throw new Error("PRIVATE_KEY is required in .env file"); const erc20 = new ethers2.Contract(tokenAddress, erc20ABI, this.auth.wallet); const vaultAddress = VAULT_ADDRESS[this.auth.network]; const vaultContract = new ethers2.Contract( vaultAddress, vault_abi_default, this.auth.wallet ); const minDepositAmount = await vaultContract.minDeposits(tokenAddress); const decimals = await erc20.decimals(); const amountToDeposit = ethers2.parseUnits(amount.toString(), decimals); const tokenSymbol = await erc20.symbol(); if (amountToDeposit < minDepositAmount) { throw new Error( `Minimum deposit ${ethers2.formatUnits( minDepositAmount, decimals )} ${tokenSymbol}` ); } const allowance = await erc20.allowance( this.auth.wallet.address, vaultAddress ); console.log( `Depositing ${amount} ${tokenSymbol} to DESK Exchange for ${this.auth.getSubaccount()}` ); if (allowance < amountToDeposit) { const tx2 = await erc20.approve(vaultAddress, amountToDeposit); console.log(`Approving ${amount} ${tokenSymbol}...`); await tx2.wait(); console.log(`Approval success!`); } const tx = await vaultContract.deposit( tokenAddress, this.auth.getSubaccount(), amountToDeposit ); const receipt = await tx.wait(); console.log("Deposit successful!"); return receipt; } async withdrawCollateral(tokenAddress, amount) { if (!this.auth.wallet) throw new Error("PRIVATE_KEY is required in .env file"); const erc20 = new ethers2.Contract(tokenAddress, erc20ABI, this.auth.wallet); const vaultAddress = VAULT_ADDRESS[this.auth.network]; const vaultContract = new ethers2.Contract( vaultAddress, vault_abi_default, this.auth.wallet ); const decimals = await erc20.decimals(); const amountToWithdraw = ethers2.parseUnits(amount.toString(), decimals); const tokenSymbol = await erc20.symbol(); console.log( `Withdrawing ${amount} ${tokenSymbol} from DESK Exchange from ${this.auth.getSubaccount()}` ); const tx = await vaultContract.withdraw( tokenAddress, this.auth.getSubaccount(), amountToWithdraw ); const receipt = await tx.wait(); console.log("Withdrawal successful!"); return receipt; } async getSubAccountSummary() { await this.parent.ensureInitialized(); const response = await this.auth.client.get( `/v2/subaccount-summary/${this.auth.getSubaccount()}` ); return response.data.data; } async placeOrder(request) { await this.parent.ensureInitialized(); const response = await this.auth.client.post(`v2/place-order`, { symbol: request.symbol, subaccount: this.auth.getSubaccount(), amount: request.amount, price: request.price, side: request.side, nonce: this.auth.generateNonce(), broker_id: BROKER_ID, order_type: request.orderType, reduce_only: request.reduceOnly, time_in_force: request.timeInForce, wait_for_reply: request.waitForReply }); return response.data.data; } async batchPlaceOrder(requests) { await this.parent.ensureInitialized(); const response = await this.auth.client.post( `v2/batch-place-order`, requests.map( (request) => ({ symbol: request.symbol, subaccount: this.auth.getSubaccount(), amount: request.amount, price: request.price, side: request.side, nonce: this.auth.generateNonce(), broker_id: BROKER_ID, order_type: request.orderType, reduce_only: request.reduceOnly, time_in_force: request.timeInForce, wait_for_reply: request.waitForReply }) ) ); return response.data.data; } async cancelOrder(request) { await this.parent.ensureInitialized(); const response = await this.auth.client.post(`/v2/cancel-order`, { symbol: request.symbol, subaccount: this.auth.getSubaccount(), nonce: this.auth.generateNonce(), order_digest: request.orderDigest, is_conditional_order: false, wait_for_reply: request.waitForReply ?? false }); return response.data.data; } async batchCancelOrder(requests) { await this.parent.ensureInitialized(); const cancelRequests = requests.map((request) => this.cancelOrder(request)); return Promise.all(cancelRequests); } }; // src/websocket/connection.ts import WebSocket from "ws"; import { EventEmitter } from "events"; var WebSocketClient = class extends EventEmitter { ws = null; url; pingInterval = null; reconnectAttempts = 0; maxReconnectAttempts = 5; initialReconnectDelay = 1e3; maxReconnectDelay = 3e4; constructor(auth) { super(); this.url = WSS_URLS[auth.network]; } connect() { return new Promise((resolve, reject) => { this.ws = new WebSocket(this.url); this.ws.on("open", () => { console.log("WebSocket connected"); this.reconnectAttempts = 0; this.startPingInterval(); resolve(); }); this.ws.on("message", (data) => { const message = JSON.parse(data.toString()); this.emit("message", message); }); this.ws.on("error", (error) => { console.error("WebSocket error:", error); reject(error); }); this.ws.on("close", () => { console.log("WebSocket disconnected"); this.stopPingInterval(); this.reconnect(); }); }); } reconnect() { if (this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnectAttempts++; const delay = Math.min( this.initialReconnectDelay * Math.pow(2, this.reconnectAttempts - 1), this.maxReconnectDelay ); console.log( `Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts}) in ${delay}ms...` ); setTimeout(() => this.connect(), delay); } else { console.error( "Max reconnection attempts reached. Please reconnect manually." ); this.emit("maxReconnectAttemptsReached"); } } startPingInterval() { this.pingInterval = setInterval(() => { this.sendMessage({ method: "ping" }); }, 15e3); } stopPingInterval() { if (this.pingInterval) { clearInterval(this.pingInterval); this.pingInterval = null; } } sendMessage(message) { if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { throw new Error("WebSocket is not connected"); } this.ws.send(JSON.stringify(message)); } close() { if (this.ws) { this.ws.close(); } this.stopPingInterval(); } removeListener(event, listener) { super.removeListener(event, listener); return this; } removeAllListeners(event) { super.removeAllListeners(event); return this; } }; // src/websocket/subscriptions.ts var WebSocketSubscriptions = class { ws; parent; subscriptions = /* @__PURE__ */ new Map(); constructor(ws, parent) { this.ws = ws; this.parent = parent; } getSubscriptionKey(subscription) { return JSON.stringify(subscription); } addSubscription(subscription, callback, messageHandler) { const key = this.getSubscriptionKey(subscription); if (!this.subscriptions.has(key)) { this.subscriptions.set(key, /* @__PURE__ */ new Set()); } this.subscriptions.get(key)?.add({ callback, messageHandler }); } async subscribe(subscription) { await this.parent.ensureInitialized(); await this.ws.sendMessage({ method: "subscribe", subscription }); } async unsubscribe(subscription) { await this.parent.ensureInitialized(); await this.ws.sendMessage({ method: "unsubscribe", subscription }); } removeSubscription(subscription) { const key = this.getSubscriptionKey(subscription); const callbacks = this.subscriptions.get(key); if (callbacks) { for (const { messageHandler } of callbacks) { this.ws.removeListener("message", messageHandler); } this.subscriptions.delete(key); } } async subscribeToMarkPrices(callback) { if (typeof callback !== "function") { throw new Error("Callback must be a function"); } const subscription = { type: "markPricesV2" /* MarkPrices */ }; const messageHandler = (message) => { if (message.type === "markPricesV2" && message.data) { const markPrices = message.data.map((item) => ({ symbol: item.symbol, markPrice: item.mark_price, indexPrice: item.index_price })); callback(markPrices); } }; this.addSubscription(subscription, callback, messageHandler); this.ws.on("message", messageHandler); await this.subscribe(subscription); } async unsubscribeFromMarkPrices() { const subscription = { type: "markPricesV2" /* MarkPrices */ }; this.removeSubscription(subscription); await this.unsubscribe(subscription); } async subscribeToOrderbook(symbol, callback) { if (typeof callback !== "function") { throw new Error("Callback must be a function"); } const subscription = { type: "l2BookV2" /* Orderbook */, symbol }; const messageHandler = (message) => { if (message.type === "l2BookV2" /* Orderbook */ && message.data) { callback(message.data); } }; this.addSubscription(subscription, callback, messageHandler); this.ws.on("message", messageHandler); await this.subscribe(subscription); } async unsubscribeFromOrderbook(symbol) { const subscription = { type: "l2BookV2" /* Orderbook */, symbol }; this.removeSubscription(subscription); await this.unsubscribe(subscription); } async subscribeToTrades(symbol, callback) { if (typeof callback !== "function") { throw new Error("Callback must be a function"); } const subscription = { type: "tradesV2" /* Trades */, symbol }; const messageHandler = (message) => { if (message.type === "tradesV2" /* Trades */ && message.data) { callback(message.data); } }; this.addSubscription(subscription, callback, messageHandler); this.ws.on("message", messageHandler); await this.subscribe(subscription); } async unsubscribeFromTrades(symbol) { const subscription = { type: "tradesV2" /* Trades */, symbol }; this.removeSubscription(subscription); await this.unsubscribe(subscription); } async subscribeToCollateralPrices(callback) { if (typeof callback !== "function") { throw new Error("Callback must be a function"); } const subscription = { type: "collateralPricesV2" /* CollateralPrices */ }; const messageHandler = (message) => { if (message.type === "collateralPricesV2" /* CollateralPrices */ && message.data) { callback(message.data); } }; this.addSubscription(subscription, callback, messageHandler); this.ws.on("message", messageHandler); await this.subscribe(subscription); } async unsubscribeFromCollateralPrices(symbol) { const subscription = { type: "collateralPricesV2" /* CollateralPrices */, symbol }; this.removeSubscription(subscription); await this.unsubscribe(subscription); } async subscribeToOrderUpdates(subaccount, callback) { if (typeof callback !== "function") { throw new Error("Callback must be a function"); } const subscription = { type: "orderUpdatesV2" /* OrderUpdatesV2 */, subaccount: subaccount || this.parent.auth.getSubaccount() }; const messageHandler = (message) => { if (message.type === "orderUpdatesV2" /* OrderUpdatesV2 */ && message.data) { callback(message.data); } }; this.addSubscription(subscription, callback, messageHandler); this.ws.on("message", messageHandler); await this.subscribe(subscription); } async unsubscribeFromOrderUpdates(symbol) { const subscription = { type: "orderUpdatesV2" /* OrderUpdatesV2 */, symbol }; this.removeSubscription(subscription); await this.unsubscribe(subscription); } async subscribeToPositionUpdates(subaccount, callback) { if (typeof callback !== "function") { throw new Error("Callback must be a function"); } const subscription = { type: "positionUpdatesV2" /* PositionUpdatesV2 */, subaccount: subaccount || this.parent.auth.getSubaccount() }; const messageHandler = (message) => { if (message.type === "positionUpdatesV2" /* PositionUpdatesV2 */ && message.data) { callback(message.data); } }; this.addSubscription(subscription, callback, messageHandler); this.ws.on("message", messageHandler); await this.subscribe(subscription); } async unsubscribeFromPositionUpdates(symbol) { const subscription = { type: "positionUpdatesV2" /* PositionUpdatesV2 */, symbol }; this.removeSubscription(subscription); await this.unsubscribe(subscription); } }; // src/api/info.ts var Info = class { auth; parent; constructor(auth, parent) { this.auth = auth; this.parent = parent; } async getMarketInfos() { const response = await this.auth.client.get( `/v2/market-info/brokers/${BROKER_ID}` ); return response.data.data; } async getCollateralInfos() { const response = await this.auth.client.get(`/v2/collaterals`); return response.data.data; } async getHistoricalFundingRates(symbol, from, to) { const response = await this.auth.client.get( `/v2/funding-rate-history/${symbol}`, { params: { from, to } } ); return response.data.data; } // Get current 1h funding rate async getCurrentFundingRate(symbol) { const response = await this.auth.client.get("/v2/premium-index", { params: { symbol } }); return response.data.data.last_funding_rate; } }; // src/types/index.ts var OrderUpdateStatus = /* @__PURE__ */ ((OrderUpdateStatus2) => { OrderUpdateStatus2["Open"] = "Open"; OrderUpdateStatus2["Filled"] = "Filled"; OrderUpdateStatus2["Canceled"] = "Canceled"; OrderUpdateStatus2["Expired"] = "Expired"; OrderUpdateStatus2["NotFound"] = "NotFound"; return OrderUpdateStatus2; })(OrderUpdateStatus || {}); var OrderUpdateClientStatus = /* @__PURE__ */ ((OrderUpdateClientStatus2) => { OrderUpdateClientStatus2["PartialFilled"] = "PartialFilled"; return OrderUpdateClientStatus2; })(OrderUpdateClientStatus || {}); // src/index.ts var DeskExchange = class { auth; exchange; info; wsClient; subscriptions; enableWs; initialized; constructor(params) { this.auth = new Auth( params.network, params.privateKey, params.subAccountId ); this.exchange = new Exchange(this.auth, this); this.info = new Info(this.auth, this); this.wsClient = new WebSocketClient(this.auth); this.subscriptions = new WebSocketSubscriptions(this.wsClient, this); this.enableWs = params.enableWs; this.initialized = false; } async initialize() { await this.auth.generateJwt(); if (this.enableWs) await this.wsClient.connect(); this.initialized = true; } async ensureInitialized() { if (!this.initialized) { await this.initialize(); } } async authenticate() { await this.auth.generateJwt(); } isInitialized() { return this.initialized; } }; export { DeskExchange, OrderUpdateClientStatus, OrderUpdateStatus };