TypeScript SDK

Account Management

Account information, balances, positions, and margin data

Account Management

Access account information, balances, positions, and margin data using the TypeScript SDK.

Account Overview

The SDK provides access to account data through the main client and specialized sub-clients:

import { Client } from '@luxfi/trading';

const client = new Client({
  rpcUrl: 'http://localhost:8080/rpc',
  wsUrl: 'ws://localhost:8081'
});

// Market data client for margin info
const marketData = client.marketData;

// Liquidation monitor for risk alerts
const liquidationMonitor = client.liquidationMonitor;

Margin Information

Get Margin Status

import { Client, MarginInfo } from '@luxfi/trading';

async function getMarginStatus(userId: string): Promise<MarginInfo> {
  const client = new Client({
    rpcUrl: 'http://localhost:8080/rpc'
  });

  const margin = await client.marketData.getMarginInfo(userId);

  console.log('Margin Status:');
  console.log(`  User ID: ${margin.userId}`);
  console.log(`  Initial Margin: $${margin.initialMargin.toLocaleString()}`);
  console.log(`  Maintenance Margin: $${margin.maintenanceMargin.toLocaleString()}`);
  console.log(`  Margin Ratio: ${(margin.marginRatio * 100).toFixed(2)}%`);
  console.log(`  Free Margin: $${margin.freeMargin.toLocaleString()}`);
  console.log(`  Margin Level: ${margin.marginLevel.toFixed(2)}`);

  return margin;
}

Margin Info Interface

interface MarginInfo {
  userId: string;
  initialMargin: number;       // Required margin for positions
  maintenanceMargin: number;   // Minimum margin to avoid liquidation
  marginRatio: number;         // Current margin / required margin
  freeMargin: number;          // Available for new positions
  marginLevel: number;         // Equity / maintenance margin
}

Liquidation Risk

Check Liquidation Risk

import { Client, LiquidationRisk } from '@luxfi/trading';

async function checkLiquidationRisk(userId: string): Promise<LiquidationRisk> {
  const client = new Client({
    rpcUrl: 'http://localhost:8080/rpc'
  });

  const risk = await client.marketData.checkLiquidationRisk(userId);

  console.log('Liquidation Risk Assessment:');
  console.log(`  Risk Level: ${risk.riskLevel.toUpperCase()}`);
  console.log(`  Margin Level: ${risk.marginLevel.toFixed(2)}`);
  console.log(`  Liquidation Price: $${risk.liquidationPrice.toLocaleString()}`);

  if (risk.timeToLiquidation !== null) {
    console.log(`  Time to Liquidation: ${risk.timeToLiquidation}ms`);
  }

  if (risk.recommendations.length > 0) {
    console.log('  Recommendations:');
    risk.recommendations.forEach(r => console.log(`    - ${r}`));
  }

  return risk;
}

Liquidation Risk Interface

interface LiquidationRisk {
  userId: string;
  riskLevel: 'low' | 'medium' | 'high' | 'critical';
  marginLevel: number;
  liquidationPrice: number;
  timeToLiquidation: number | null;  // Estimated time in ms
  recommendations: string[];
}

Risk Level Actions

import { LiquidationRisk } from '@luxfi/trading';

function handleRiskLevel(risk: LiquidationRisk): void {
  switch (risk.riskLevel) {
    case 'low':
      console.log('Position is healthy');
      break;

    case 'medium':
      console.log('Warning: Consider reducing position size');
      // Optional: Send notification
      break;

    case 'high':
      console.log('Alert: High liquidation risk');
      // Reduce position or add margin
      break;

    case 'critical':
      console.log('CRITICAL: Immediate action required');
      // Emergency position reduction
      break;
  }
}

Recent Liquidations

Query Liquidations

import { Client, LiquidationInfo } from '@luxfi/trading';

async function getRecentLiquidations(symbol: string): Promise<LiquidationInfo[]> {
  const client = new Client({
    rpcUrl: 'http://localhost:8080/rpc'
  });

  const liquidations = await client.marketData.getLiquidations(symbol, 100);

  console.log(`Recent Liquidations for ${symbol}:`);
  liquidations.forEach(liq => {
    console.log(`  User: ${liq.userId}`);
    console.log(`  Size: ${liq.size}`);
    console.log(`  Liquidation Price: $${liq.liquidationPrice}`);
    console.log(`  Mark Price: $${liq.markPrice}`);
    console.log(`  Status: ${liq.status}`);
    console.log(`  Time: ${liq.timestamp.toLocaleString()}`);
    console.log('  ---');
  });

  return liquidations;
}

Liquidation Info Interface

interface LiquidationInfo {
  userId: string;
  positionId: string;
  symbol: string;
  size: number;
  liquidationPrice: number;
  markPrice: number;
  status: string;
  timestamp: Date;
}

Real-Time Monitoring

Subscribe to Liquidations

import { Client, LiquidationInfo } from '@luxfi/trading';

async function monitorLiquidations(): Promise<void> {
  const client = new Client({
    rpcUrl: 'http://localhost:8080/rpc',
    wsUrl: 'ws://localhost:8081'
  });

  await client.connect();

  client.liquidationMonitor.subscribeLiquidations((liquidation: LiquidationInfo) => {
    console.log('LIQUIDATION EVENT:');
    console.log(`  User: ${liquidation.userId}`);
    console.log(`  Symbol: ${liquidation.symbol}`);
    console.log(`  Size: ${liquidation.size}`);
    console.log(`  Price: $${liquidation.liquidationPrice}`);
  });

  console.log('Monitoring liquidations...');
}

Subscribe to Margin Calls

import { Client } from '@luxfi/trading';

interface MarginCallEvent {
  userId: string;
  marginLevel: number;
  requiredAction: string;
  deadline: Date;
}

async function monitorMarginCalls(userId: string): Promise<void> {
  const client = new Client({
    rpcUrl: 'http://localhost:8080/rpc',
    wsUrl: 'ws://localhost:8081'
  });

  await client.connect();

  client.liquidationMonitor.subscribeMarginCalls(userId, (event: MarginCallEvent) => {
    console.log('MARGIN CALL:');
    console.log(`  Margin Level: ${event.marginLevel}`);
    console.log(`  Required Action: ${event.requiredAction}`);
    console.log(`  Deadline: ${event.deadline.toLocaleString()}`);
  });

  console.log(`Monitoring margin calls for ${userId}...`);
}

Settlement Information

Get Settlement Batch

import { Client, SettlementBatch } from '@luxfi/trading';

async function getSettlementInfo(batchId: number): Promise<SettlementBatch> {
  const client = new Client({
    rpcUrl: 'http://localhost:8080/rpc'
  });

  const batch = await client.marketData.getSettlementBatch(batchId);

  console.log('Settlement Batch:');
  console.log(`  Batch ID: ${batch.batchId}`);
  console.log(`  Status: ${batch.status}`);
  console.log(`  Orders: ${batch.orderIds.length}`);

  if (batch.txHash) {
    console.log(`  TX Hash: ${batch.txHash}`);
  }
  if (batch.gasUsed) {
    console.log(`  Gas Used: ${batch.gasUsed}`);
  }

  console.log(`  Timestamp: ${batch.timestamp.toLocaleString()}`);

  return batch;
}

Settlement Batch Interface

interface SettlementBatch {
  batchId: number;
  orderIds: number[];
  status: string;
  txHash?: string;
  gasUsed?: number;
  timestamp: Date;
}

Subscribe to Settlements

import { Client, SettlementBatch } from '@luxfi/trading';

async function monitorSettlements(): Promise<void> {
  const client = new Client({
    rpcUrl: 'http://localhost:8080/rpc',
    wsUrl: 'ws://localhost:8081'
  });

  await client.connect();

  client.liquidationMonitor.subscribeSettlements((settlement: SettlementBatch) => {
    console.log('SETTLEMENT:');
    console.log(`  Batch: ${settlement.batchId}`);
    console.log(`  Orders: ${settlement.orderIds.length}`);
    console.log(`  Status: ${settlement.status}`);
  });

  console.log('Monitoring settlements...');
}

Insurance Fund

Get Insurance Fund Status

import { Client, InsuranceFundStatus } from '@luxfi/trading';

async function getInsuranceFundStatus(): Promise<InsuranceFundStatus> {
  const client = new Client({
    rpcUrl: 'http://localhost:8080/rpc'
  });

  const fund = await client.marketData.getInsuranceFundStatus();

  console.log('Insurance Fund Status:');
  console.log(`  Total Fund: $${fund.totalFund.toLocaleString()}`);
  console.log(`  Available: $${fund.availableFund.toLocaleString()}`);
  console.log(`  Used: $${fund.usedFund.toLocaleString()}`);
  console.log(`  Pending Claims: ${fund.pendingClaims}`);
  console.log(`  Last Update: ${fund.lastUpdate.toLocaleString()}`);

  return fund;
}

Insurance Fund Interface

interface InsuranceFundStatus {
  totalFund: number;
  availableFund: number;
  usedFund: number;
  pendingClaims: number;
  lastUpdate: Date;
}

React Hooks

useMargin Hook

import { useState, useEffect } from 'react';
import { Client, MarginInfo } from '@luxfi/trading';

interface UseMarginResult {
  margin: MarginInfo | null;
  loading: boolean;
  error: Error | null;
  refresh: () => Promise<void>;
}

export function useMargin(
  client: Client | null,
  userId: string
): UseMarginResult {
  const [margin, setMargin] = useState<MarginInfo | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  const fetchMargin = async (): Promise<void> => {
    if (!client) return;

    try {
      const data = await client.marketData.getMarginInfo(userId);
      setMargin(data);
      setError(null);
    } catch (err) {
      setError(err instanceof Error ? err : new Error('Failed to fetch margin'));
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchMargin();

    // Refresh every 5 seconds
    const interval = setInterval(fetchMargin, 5000);
    return () => clearInterval(interval);
  }, [client, userId]);

  return {
    margin,
    loading,
    error,
    refresh: fetchMargin
  };
}

useLiquidationRisk Hook

import { useState, useEffect } from 'react';
import { Client, LiquidationRisk } from '@luxfi/trading';

interface UseLiquidationRiskResult {
  risk: LiquidationRisk | null;
  loading: boolean;
  error: Error | null;
}

export function useLiquidationRisk(
  client: Client | null,
  userId: string
): UseLiquidationRiskResult {
  const [risk, setRisk] = useState<LiquidationRisk | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    if (!client) return;

    const checkRisk = async (): Promise<void> => {
      try {
        const data = await client.marketData.checkLiquidationRisk(userId);
        setRisk(data);
        setError(null);
      } catch (err) {
        setError(err instanceof Error ? err : new Error('Failed to check risk'));
      } finally {
        setLoading(false);
      }
    };

    checkRisk();

    // Check more frequently for high-risk users
    const getInterval = (): number => {
      if (risk?.riskLevel === 'critical') return 1000;
      if (risk?.riskLevel === 'high') return 2000;
      if (risk?.riskLevel === 'medium') return 5000;
      return 10000;
    };

    const interval = setInterval(checkRisk, getInterval());
    return () => clearInterval(interval);
  }, [client, userId, risk?.riskLevel]);

  return { risk, loading, error };
}

Account Dashboard Component

import React from 'react';
import { useMargin, useLiquidationRisk } from './hooks';
import { useDexClient } from './DexProvider';

interface AccountDashboardProps {
  userId: string;
}

function AccountDashboard({ userId }: AccountDashboardProps): JSX.Element {
  const { client } = useDexClient();
  const { margin, loading: marginLoading } = useMargin(client, userId);
  const { risk, loading: riskLoading } = useLiquidationRisk(client, userId);

  if (marginLoading || riskLoading) {
    return <div>Loading account data...</div>;
  }

  return (
    <div className="account-dashboard">
      <div className="margin-info">
        <h3>Margin Status</h3>
        {margin && (
          <dl>
            <dt>Initial Margin</dt>
            <dd>${margin.initialMargin.toLocaleString()}</dd>

            <dt>Maintenance Margin</dt>
            <dd>${margin.maintenanceMargin.toLocaleString()}</dd>

            <dt>Free Margin</dt>
            <dd>${margin.freeMargin.toLocaleString()}</dd>

            <dt>Margin Level</dt>
            <dd>{margin.marginLevel.toFixed(2)}</dd>
          </dl>
        )}
      </div>

      <div className={`risk-indicator ${risk?.riskLevel}`}>
        <h3>Risk Level</h3>
        {risk && (
          <>
            <div className="risk-badge">{risk.riskLevel.toUpperCase()}</div>
            <p>Liquidation Price: ${risk.liquidationPrice.toLocaleString()}</p>

            {risk.recommendations.length > 0 && (
              <ul className="recommendations">
                {risk.recommendations.map((rec, i) => (
                  <li key={i}>{rec}</li>
                ))}
              </ul>
            )}
          </>
        )}
      </div>
    </div>
  );
}

export default AccountDashboard;

Account Monitoring Class

Complete Account Monitor

import { Client, MarginInfo, LiquidationRisk, LiquidationInfo } from '@luxfi/trading';

interface AccountMonitorOptions {
  marginCheckInterval?: number;
  riskCheckInterval?: number;
  onMarginUpdate?: (margin: MarginInfo) => void;
  onRiskUpdate?: (risk: LiquidationRisk) => void;
  onLiquidation?: (liquidation: LiquidationInfo) => void;
  onMarginCall?: (event: unknown) => void;
}

export class AccountMonitor {
  private client: Client;
  private userId: string;
  private options: AccountMonitorOptions;
  private marginInterval: NodeJS.Timeout | null = null;
  private riskInterval: NodeJS.Timeout | null = null;
  private running: boolean = false;

  constructor(
    client: Client,
    userId: string,
    options: AccountMonitorOptions = {}
  ) {
    this.client = client;
    this.userId = userId;
    this.options = {
      marginCheckInterval: 5000,
      riskCheckInterval: 2000,
      ...options
    };
  }

  async start(): Promise<void> {
    if (this.running) return;
    this.running = true;

    // Connect WebSocket for real-time events
    await this.client.connect();

    // Start margin monitoring
    this.marginInterval = setInterval(async () => {
      try {
        const margin = await this.client.marketData.getMarginInfo(this.userId);
        this.options.onMarginUpdate?.(margin);
      } catch (error) {
        console.error('Margin check failed:', error);
      }
    }, this.options.marginCheckInterval);

    // Start risk monitoring
    this.riskInterval = setInterval(async () => {
      try {
        const risk = await this.client.marketData.checkLiquidationRisk(this.userId);
        this.options.onRiskUpdate?.(risk);

        // Adjust check frequency based on risk level
        if (risk.riskLevel === 'critical' && this.riskInterval) {
          clearInterval(this.riskInterval);
          this.riskInterval = setInterval(async () => {
            const r = await this.client.marketData.checkLiquidationRisk(this.userId);
            this.options.onRiskUpdate?.(r);
          }, 500);
        }
      } catch (error) {
        console.error('Risk check failed:', error);
      }
    }, this.options.riskCheckInterval);

    // Subscribe to liquidation events
    this.client.liquidationMonitor.subscribeLiquidations((liq) => {
      if (liq.userId === this.userId) {
        this.options.onLiquidation?.(liq);
      }
    });

    // Subscribe to margin calls
    this.client.liquidationMonitor.subscribeMarginCalls(this.userId, (event) => {
      this.options.onMarginCall?.(event);
    });

    console.log(`Account monitor started for ${this.userId}`);
  }

  stop(): void {
    if (!this.running) return;
    this.running = false;

    if (this.marginInterval) {
      clearInterval(this.marginInterval);
      this.marginInterval = null;
    }

    if (this.riskInterval) {
      clearInterval(this.riskInterval);
      this.riskInterval = null;
    }

    this.client.liquidationMonitor.unsubscribe('liquidations');
    this.client.liquidationMonitor.unsubscribe(`margin_calls:${this.userId}`);

    console.log(`Account monitor stopped for ${this.userId}`);
  }
}

// Usage
async function runAccountMonitor(): Promise<void> {
  const client = new Client({
    rpcUrl: 'http://localhost:8080/rpc',
    wsUrl: 'ws://localhost:8081'
  });

  const monitor = new AccountMonitor(client, 'trader-001', {
    onMarginUpdate: (margin) => {
      console.log('Margin:', margin.marginLevel);
    },
    onRiskUpdate: (risk) => {
      if (risk.riskLevel !== 'low') {
        console.log('Risk alert:', risk.riskLevel);
      }
    },
    onLiquidation: (liq) => {
      console.log('LIQUIDATED:', liq);
    },
    onMarginCall: (event) => {
      console.log('MARGIN CALL:', event);
    }
  });

  await monitor.start();

  // Stop after 1 hour
  setTimeout(() => monitor.stop(), 3600000);
}

Next Steps