altangent / ccxws

WebSocket client for 38 cryptocurrency exchanges
MIT License
619 stars 187 forks source link

Implement in TypeScript #229

Closed jimmy4701 closed 3 years ago

jimmy4701 commented 3 years ago

The project is perfect but we'd need a typescript implementation of ccxws, to work well in a Typescript environment.

Maybe just a declaration file Maybe just a declaration file (like in ccxt) would do the job, instead of re-developping all the project in TS ?

bmancini55 commented 3 years ago

@jimmy4701 thanks for submitting the issue!

We're planning to fully convert the library to TypeScript with the refactor in #149.

Until that happens, a declaration file certainly seems like a easy enough path forward. Happy to accept a PR for it if there is interest in helping with the library!

jimmy4701 commented 3 years ago

@bmancini55 , thanks for your reply .

No problem, so we'll wait until the push of #149 👍

We're already using a declaration file, but a complete implementation of the types would be more effective :P I also already asked the dev team to develop it by themself, to make our first PR to CCXWS, cause it would be very cool to help the project, after the lot of time it made us winning :D So it would be our pleasure to help you.

Shepless commented 3 years ago

@jimmy4701 If you need type definitions until the migration is done:

1) Create a typings directory 2) Create a new file ccxws.d.ts file 3) Copy and paste type definitions (below) 4) Update your tsconfig.json to include the new typings (example below)

tsconfig.json

"compilerOptions": {
        // ... your existing config
        "typeRoots": [
            "./node_modules/@types",
            "./typings"
        ]
}

Type Defintions

declare module "ccxws" {
    type ExchangeCtor = new (options?: IExchangeOptions) => IExchange;
    type ConnectionEventType = 'connecting' | 'connected' | 'disconnected' | 'closing' | 'closed' | 'reconnecting';
    type ExchangeEventType = 'ticker' | 'candle' | 'trade' | 'l2snapshot' | 'l2update' | 'l3snapshot' | 'l3update' | 'error';
    type EventType = ConnectionEventType | ExchangeEventType;
    type CandlePeriod = {
        _1m: '_1m',
        _2m: '_2m',
        _3m: '_3m',
        _5m: '_5m',
        _15m: '_15m',
        _30m: '_30m',
        _1h: '_1h',
        _2h: '_2h',
        _4h: '_4h',
        _6h: '_6h',
        _8h: '_8h',
        _12h: '_12h',
        _1d: '_1d',
        _3d: '_3d',
        _1w: '_1w',
        _2w: '_2w',
        _1M: '_1M'
    };

    interface ITicker {
        exchange: string;
        base: string;
        quote: string;
        timestamp: number;
        last: string;
        open: string;
        low: string;
        high: string;
        volume: string;
        quoteVolume: string;
        change: string;
        changePercent: string;
        bid: string;
        bidVolume: string;
        ask: string;
        askVolume: string;
    }

    interface ITrade {
        exchange: string;
        base: string;
        quote: string;
        tradeId: string;
        unix: number;
        side: string;
        price: string;
        amount: string;
        buyOrderId?: string;
        sellOrderId?: string;
    }

    interface ICandle {
        timestampMs: number;
        open: string;
        high: string;
        low: string;
        close: string;
        volume: string;
    }

    interface ILevelData<T> {
        exchange: string;
        base: string;
        quote: string;
        timestampMs?: number;
        sequenceId?: number;
        asks: T[];
        bids: T[];
    }

    interface ILevel2Point {
        price: string;
        size: string;
        count?: number;
    }

    interface ILevel3Point {
        orderId: string;
        price: string;
        size: string;
        meta?: any;
    }

    interface ILevel2Data extends ILevelData<ILevel2Point> { }

    interface ILevel3Data extends ILevelData<ILevel3Point> { }

    interface IMarket {
        id: string;
        base: string;
        quote: string;
        type?: string;
    }

    interface IExchangeOptions {
        wssPath?: string;
        watcherMs?: number;
        apiKey?: string
        apiSecret?: string;
    }

    interface EventCallbackMap {
        'connecting': () => void;
        'connected': () => void;
        'disconnected': () => void;
        'closing': () => void;
        'closed': () => void;
        'reconnecting': () => void;
        'error': (error: Error) => void;
        'ticker': (ticker: ITicker, market: IMarket) => void;
        'trade': (trade: ITrade, market: IMarket) => void;
        'candle': (candle: ICandle, market: IMarket) => void;
        'l2snapshot': (snapshot: ILevel2Data, market: IMarket) => void;
        'l2update': (snapshot: ILevel2Data, market: IMarket) => void;
        'l3snapshot': (snapshot: ILevel3Data, market: IMarket) => void;
        'l3update': (snapshot: ILevel3Data, market: IMarket) => void;
    }

    interface IExchange {
        candlePeriod: keyof CandlePeriod;
        hasTickers: boolean;
        hasTrades: boolean;
        hasCandles: boolean;
        hasLevel2Snapshots: boolean;
        hasLevel2Updates: boolean;
        hasLevel3Snapshots: boolean;
        hasLevel3Updates: boolean;
        on<T extends EventType>(event: T, callback: EventCallbackMap[T]): void;
        subscribeTicker(market: IMarket): void;
        unsubscribeTicker(market: IMarket): void;
        subscribeTrades(market: IMarket): void;
        unsubscribeTrades(market: IMarket): void;
        subscribeCandles(market: IMarket): void;
        unsubscribeCandles(market: IMarket): void;
        subscribeLevel2Snapshots(market: IMarket): void;
        unsubscribeLevel2Snapshots(market: IMarket): void;
        subscribeLevel2Updates(market: IMarket): void;
        unsubscribeLevel2Updates(market: IMarket): void;
        subscribeLevel3Snapshots(market: IMarket): void;
        unsubscribeLevel3Snapshots(market: IMarket): void;
        subscribeLevel3Updates(market: IMarket): void;
        unsubscribeLevel3Updates(market: IMarket): void;
    }

    interface ICCXWS {
        Bibox: ExchangeCtor;
        Binance: ExchangeCtor;
        BinanceFuturesCoinM: ExchangeCtor;
        BinanceFuturesUsdtM: ExchangeCtor;
        BinanceJe: ExchangeCtor;
        BinanceUs: ExchangeCtor;
        Bitfinex: ExchangeCtor;
        Bitflyer: ExchangeCtor;
        Bithumb: ExchangeCtor;
        BitMEX: ExchangeCtor;
        Bitstamp: ExchangeCtor;
        Bittrex: ExchangeCtor;
        Cex: ExchangeCtor;
        CoinbasePro: ExchangeCtor;
        Coinex: ExchangeCtor;
        Deribit: ExchangeCtor;
        Digifinex: ExchangeCtor;
        Ethfinex: ExchangeCtor;
        ErisX: ExchangeCtor;
        Ftx: ExchangeCtor;
        FtxUs: ExchangeCtor;
        Gateio: ExchangeCtor;
        Gemini: ExchangeCtor;
        HitBTC: ExchangeCtor;
        Huobi: ExchangeCtor;
        HuobiFutures: ExchangeCtor;
        HuobiSwaps: ExchangeCtor;
        HuobiJapan: ExchangeCtor;
        HuobiKorea: ExchangeCtor;
        HuobiRussia: ExchangeCtor;
        Kucoin: ExchangeCtor;
        Kraken: ExchangeCtor;
        LedgerX: ExchangeCtor;
        Liquid: ExchangeCtor;
        OKEx: ExchangeCtor;
        Poloniex: ExchangeCtor;
        Upbit: ExchangeCtor;
        Zb: ExchangeCtor;
        CandlePeriod: CandlePeriod;
    }

    const ccxws: ICCXWS;
    export default ccxws;
}
bmancini55 commented 3 years ago

@Shepless thanks for putting together typedefs! If you put those into a PR I will gladly merge it!

Industrial commented 3 years ago

Hi!

Looking at the implementation of ccxt.d.ts:

  1. Remove 'I' from all interface names. This is an old convention and eslint recommends against it.
  2. Export all types.
declare module 'ccxws' {
  export type ConnectionEventType = 'connecting' | 'connected' | 'disconnected' | 'closing' | 'closed' | 'reconnecting'

  export type ExchangeEventType =
    | 'ticker'
    | 'candle'
    | 'trade'
    | 'l2snapshot'
    | 'l2update'
    | 'l3snapshot'
    | 'l3update'
    | 'error'

  export type EventType = ConnectionEventType | ExchangeEventType

  export enum CandlePeriod {
    _1m = '_1m',
    _2m = '_2m',
    _3m = '_3m',
    _5m = '_5m',
    _15m = '_15m',
    _30m = '_30m',
    _1h = '_1h',
    _2h = '_2h',
    _4h = '_4h',
    _6h = '_6h',
    _8h = '_8h',
    _12h = '_12h',
    _1d = '_1d',
    _3d = '_3d',
    _1w = '_1w',
    _2w = '_2w',
    _1M = '_1M',
  }

  export interface Ticker {
    exchange: string
    base: string
    quote: string
    timestamp: number
    last: string
    open: string
    low: string
    high: string
    volume: string
    quoteVolume: string
    change: string
    changePercent: string
    bid: string
    bidVolume: string
    ask: string
    askVolume: string
  }

  export interface Trade {
    exchange: string
    base: string
    quote: string
    tradeId: string
    unix: number
    side: string
    price: string
    amount: string
    buyOrderId?: string
    sellOrderId?: string
  }

  export interface Candle {
    timestampMs: number
    open: string
    high: string
    low: string
    close: string
    volume: string
  }

  export interface LevelData<T> {
    exchange: string
    base: string
    quote: string
    timestampMs?: number
    sequenceId?: number
    asks: T[]
    bids: T[]
  }

  export interface Level2Point {
    price: string
    size: string
    count?: number
  }

  export interface Level3Point {
    orderId: string
    price: string
    size: string
    meta?: any
  }

  export interface Level2Data extends LevelData<Level2Point> {}

  export interface Level3Data extends LevelData<Level3Point> {}

  export interface Market {
    id: string
    base: string
    quote: string
    type?: string
  }

  export interface EventCallbackMap {
    connecting: () => void
    connected: () => void
    disconnected: () => void
    closing: () => void
    closed: () => void
    reconnecting: () => void
    error: (error: Error) => void
    ticker: (ticker: Ticker, market: Market) => void
    trade: (trade: Trade, market: Market) => void
    candle: (candle: Candle, market: Market) => void
    l2snapshot: (snapshot: Level2Data, market: Market) => void
    l2update: (snapshot: Level2Data, market: Market) => void
    l3snapshot: (snapshot: Level3Data, market: Market) => void
    l3update: (snapshot: Level3Data, market: Market) => void
  }

  export interface ExchangeOptions {
    wssPath?: string
    watcherMs?: number
    apiKey?: string
    apiSecret?: string
  }

  export class Exchange {
    constructor(options?: ExchangeOptions)

    candlePeriod: keyof CandlePeriod
    hasTickers: boolean
    hasTrades: boolean
    hasCandles: boolean
    hasLevel2Snapshots: boolean
    hasLevel2Updates: boolean
    hasLevel3Snapshots: boolean
    hasLevel3Updates: boolean
    on<T extends EventType>(event: T, callback: EventCallbackMap[T]): void
    subscribeTicker(market: Market): void
    unsubscribeTicker(market: Market): void
    subscribeTrades(market: Market): void
    unsubscribeTrades(market: Market): void
    subscribeCandles(market: Market): void
    unsubscribeCandles(market: Market): void
    subscribeLevel2Snapshots(market: Market): void
    unsubscribeLevel2Snapshots(market: Market): void
    subscribeLevel2Updates(market: Market): void
    unsubscribeLevel2Updates(market: Market): void
    subscribeLevel3Snapshots(market: Market): void
    unsubscribeLevel3Snapshots(market: Market): void
    subscribeLevel3Updates(market: Market): void
    unsubscribeLevel3Updates(market: Market): void
  }

  export class Bibox extends Exchange {}

  export class Binance extends Exchange {}

  export class BinanceFuturesCoinM extends Exchange {}

  export class BinanceFuturesUsdtM extends Exchange {}

  export class BinanceJe extends Exchange {}

  export class BinanceUs extends Exchange {}

  export class Bitfinex extends Exchange {}

  export class Bitflyer extends Exchange {}

  export class Bithumb extends Exchange {}

  export class BitMEX extends Exchange {}

  export class Bitstamp extends Exchange {}

  export class Bittrex extends Exchange {}

  export class Cex extends Exchange {}

  export class CoinbasePro extends Exchange {}

  export class Coinex extends Exchange {}

  export class Deribit extends Exchange {}

  export class Digifinex extends Exchange {}

  export class Ethfinex extends Exchange {}

  export class ErisX extends Exchange {}

  export class Ftx extends Exchange {}

  export class FtxUs extends Exchange {}

  export class Gateio extends Exchange {}

  export class Gemini extends Exchange {}

  export class HitBTC extends Exchange {}

  export class Huobi extends Exchange {}

  export class HuobiFutures extends Exchange {}

  export class HuobiSwaps extends Exchange {}

  export class HuobiJapan extends Exchange {}

  export class HuobiKorea extends Exchange {}

  export class HuobiRussia extends Exchange {}

  export class Kucoin extends Exchange {}

  export class Kraken extends Exchange {}

  export class LedgerX extends Exchange {}

  export class Liquid extends Exchange {}

  export class OKEx extends Exchange {}

  export class Poloniex extends Exchange {}

  export class Upbit extends Exchange {}

  export class Zb extends Exchange {}
}
Shepless commented 3 years ago

You're welcome 👍 Happy for any updates to be made. I don't have time to PR this but if anyone else wants to then I'm more than happy for it be re-used in whatever way is needed/wanted.

bmancini55 commented 3 years ago

Closed with #292