From 952a2b194c413c50a1ee4ec5ee7fa89b9bee05cd Mon Sep 17 00:00:00 2001 From: megakaban Date: Fri, 1 Oct 2021 07:50:24 +0700 Subject: [PATCH] Initial commit --- .gitignore | 1 + .prettierrc | 3 + dist/binance/apiTypes.d.ts | 3 + dist/binance/apiTypes.js | 38 ++ dist/binance/client.d.ts | 25 + dist/binance/client.js | 17 + dist/binance/core.d.ts | 267 ++++++++++ dist/binance/core.js | 124 +++++ dist/binance/socketTypes.d.ts | 285 +++++++++++ dist/binance/socketTypes.js | 282 +++++++++++ dist/generate.d.ts | 4 + dist/generate.js | 66 +++ dist/index.d.ts | 4 + dist/index.js | 16 + package-lock.json | 910 ++++++++++++++++++++++++++++++++++ package.json | 46 ++ src/binance/apiTypes.ts | 56 +++ src/binance/core.ts | 298 +++++++++++ src/binance/socketTypes.ts | 356 +++++++++++++ src/generate.ts | 80 +++ src/index.ts | 4 + tsconfig.json | 23 + 22 files changed, 2908 insertions(+) create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 dist/binance/apiTypes.d.ts create mode 100644 dist/binance/apiTypes.js create mode 100644 dist/binance/client.d.ts create mode 100644 dist/binance/client.js create mode 100644 dist/binance/core.d.ts create mode 100644 dist/binance/core.js create mode 100644 dist/binance/socketTypes.d.ts create mode 100644 dist/binance/socketTypes.js create mode 100644 dist/generate.d.ts create mode 100644 dist/generate.js create mode 100644 dist/index.d.ts create mode 100644 dist/index.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/binance/apiTypes.ts create mode 100644 src/binance/core.ts create mode 100644 src/binance/socketTypes.ts create mode 100644 src/generate.ts create mode 100644 src/index.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..544138b --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/dist/binance/apiTypes.d.ts b/dist/binance/apiTypes.d.ts new file mode 100644 index 0000000..a16863f --- /dev/null +++ b/dist/binance/apiTypes.d.ts @@ -0,0 +1,3 @@ +import * as t from 'io-ts'; +export declare const BinanceKlineIO: t.TupleType<[t.NumberC, t.StringC, t.StringC, t.StringC, t.StringC, t.StringC, t.NumberC, t.StringC, t.NumberC, t.StringC, t.StringC, t.StringC], readonly [number, string, string, string, string, string, number, string, number, string, string, string], readonly [number, string, string, string, string, string, number, string, number, string, string, string], unknown>; +export declare type BinanceKline = t.TypeOf; diff --git a/dist/binance/apiTypes.js b/dist/binance/apiTypes.js new file mode 100644 index 0000000..08932fc --- /dev/null +++ b/dist/binance/apiTypes.js @@ -0,0 +1,38 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BinanceKlineIO = void 0; +const t = __importStar(require("io-ts")); +const tuple = t.tuple; +exports.BinanceKlineIO = tuple([ + t.number, + t.string, + t.string, + t.string, + t.string, + t.string, + t.number, + t.string, + t.number, + t.string, + t.string, + t.string, +]); diff --git a/dist/binance/client.d.ts b/dist/binance/client.d.ts new file mode 100644 index 0000000..cf9d0d0 --- /dev/null +++ b/dist/binance/client.d.ts @@ -0,0 +1,25 @@ +import { HKT, Kind, Kind2, URIS, URIS2 } from 'fp-ts/lib/HKT'; +import { MonadThrow, MonadThrow1, MonadThrow2 } from 'fp-ts/lib/MonadThrow'; +import { Errors } from 'io-ts'; +export interface Request { + readonly method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'; + readonly url: string; + readonly responseType: 'json' | 'blob' | 'text'; + readonly query?: string; + readonly body?: unknown; + readonly headers?: Record; +} +export interface HTTPClient extends MonadThrow { + readonly request: (request: Request) => HKT; +} +export interface HTTPClient1 extends MonadThrow1 { + readonly request: (request: Request) => Kind; +} +export interface HTTPClient2 extends MonadThrow2 { + readonly request: (request: Request) => Kind2; +} +export declare class ResponseValidationError extends Error { + readonly errors: Errors; + static create(errors: Errors): ResponseValidationError; + constructor(errors: Errors); +} diff --git a/dist/binance/client.js b/dist/binance/client.js new file mode 100644 index 0000000..5545559 --- /dev/null +++ b/dist/binance/client.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ResponseValidationError = void 0; +const PathReporter_1 = require("io-ts/lib/PathReporter"); +const Either_1 = require("fp-ts/lib/Either"); +class ResponseValidationError extends Error { + constructor(errors) { + super(PathReporter_1.PathReporter.report((0, Either_1.left)(errors)).join('\n\n')); + this.errors = errors; + this.name = 'ResponseValidationError'; + Object.setPrototypeOf(this, ResponseValidationError.prototype); + } + static create(errors) { + return new ResponseValidationError(errors); + } +} +exports.ResponseValidationError = ResponseValidationError; diff --git a/dist/binance/core.d.ts b/dist/binance/core.d.ts new file mode 100644 index 0000000..fe228bb --- /dev/null +++ b/dist/binance/core.d.ts @@ -0,0 +1,267 @@ +import { either } from 'fp-ts'; +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { Observable } from 'rxjs'; +import { Json } from 'fp-ts/lib/Json'; +import { BinanceInterval } from './socketTypes'; +import { observableEither } from 'fp-ts-rxjs'; +export declare const buildQueryString: (o: {}) => string; +export declare const makeSignQuery: (apiSecret: string) => >(query: T) => T & { + signature: string; + timestamp: t.Int; +}; +export declare const fromPromiseToStream: (promise: () => Promise) => Observable>; +export declare type BinanceConfig = { + apiKey: string; + apiSecret: string; +}; +interface Request { + readonly method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'; + readonly url: string; + readonly responseType: 'json' | 'blob' | 'text'; + readonly query?: string; + readonly body?: unknown; + readonly headers?: Record; +} +export declare const makeBinanceHttpClient: (baseURL: string, config: BinanceConfig) => { + signQuery: >(query: T) => T & { + signature: string; + timestamp: t.Int; + }; + httpClient: { + request: (request: Request) => Observable>; + ap: (fab: observableEither.ObservableEither B>, fa: observableEither.ObservableEither) => observableEither.ObservableEither; + URI: "ObservableEither"; + map: (fa: observableEither.ObservableEither, f: (a: A_1) => B_1) => observableEither.ObservableEither; + of: (a: A_2) => observableEither.ObservableEither; + chain: (fa: observableEither.ObservableEither, f: (a: A_3) => observableEither.ObservableEither) => observableEither.ObservableEither; + bimap: (fea: observableEither.ObservableEither, f: (e: E_4) => G, g: (a: A_4) => B_3) => observableEither.ObservableEither; + mapLeft: (fea: observableEither.ObservableEither, f: (e: E_5) => G_1) => observableEither.ObservableEither; + alt: (fa: observableEither.ObservableEither, that: import("fp-ts/lib/function").Lazy>) => observableEither.ObservableEither; + fromObservable: (fa: Observable) => observableEither.ObservableEither; + fromIO: import("fp-ts/lib/NaturalTransformation").NaturalTransformation12<"IO", "ObservableEither">; + fromTask: import("fp-ts/lib/NaturalTransformation").NaturalTransformation12<"Task", "ObservableEither">; + throwError: (e: E_8) => observableEither.ObservableEither; + }; +}; +export declare const makeWebsocketStream: (url: string, websocketImplementation?: any) => Observable>; +export declare const makeBinanceWebsocketClient: (baseURL: string, websocketImplementation?: any) => { + aggregatedTrade: (symbol: string) => Observable; + s: string; + a: t.Branded; + p: string; + q: string; + f: t.Branded; + l: t.Branded; + T: t.Branded; + m: boolean; + M: boolean; + }>>; + trade: (symbol: string) => Observable; + s: string; + t: t.Branded; + p: string; + q: string; + b: t.Branded; + a: t.Branded; + T: t.Branded; + m: boolean; + M: boolean; + }>>; + kline: (symbol: string, interval: BinanceInterval) => Observable>; + miniTicker: (symbol: string) => Observable; + s: string; + c: string; + o: string; + h: string; + l: string; + v: string; + q: string; + }>>; + miniTickers: () => Observable; + s: string; + c: string; + o: string; + h: string; + l: string; + v: string; + q: string; + }[]>>; + ticker: (symbol: string) => Observable; + s: string; + p: string; + P: string; + w: string; + x: string; + c: string; + Q: string; + b: string; + B: string; + a: string; + A: string; + o: string; + h: string; + l: string; + v: string; + q: string; + O: t.Branded; + C: t.Branded; + F: t.Branded; + L: t.Branded; + n: t.Branded; + }>>; + tickers: () => Observable; + s: string; + p: string; + P: string; + w: string; + x: string; + c: string; + Q: string; + b: string; + B: string; + a: string; + A: string; + o: string; + h: string; + l: string; + v: string; + q: string; + O: t.Branded; + C: t.Branded; + F: t.Branded; + L: t.Branded; + n: t.Branded; + }[]>>; + bookTicker: (symbol: string) => Observable; + s: string; + b: string; + B: string; + a: string; + A: string; + }>>; + bookTickers: () => Observable; + s: string; + b: string; + B: string; + a: string; + A: string; + }>>; + partialBookDepth: (symbol: string, levels: 5 | 10 | 20, speed: 100 | 1000) => Observable; + bids: [string, string][]; + asks: [string, string][]; + }>>; + diffBookDepth: (symbol: string, speed: 100 | 1000) => Observable; + s: string; + U: t.Branded; + u: t.Branded; + b: [string, string][]; + a: [string, string][]; + }>>; + userData: (listenKey: string) => Observable; + u: t.Branded; + B: { + a: string; + f: string; + l: string; + }[]; + } | { + e: "balanceUpdate"; + E: t.Branded; + a: string; + d: string; + T: t.Branded; + } | { + e: "executionReport"; + E: t.Branded; + s: string; + c: string; + S: "SELL" | "BUY"; + o: "LIMIT" | "MARKET" | "STOP_LOSS" | "STOP_LOSS_LIMIT" | "TAKE_PROFIT" | "TAKE_PROFIT_LIMIT" | "LIMIT_MAKER"; + f: "GTC" | "IOC" | "FOK"; + q: string; + p: string; + P: string; + F: string; + g: t.Branded; + C: string; + x: "NEW" | "CANCELED" | "REPLACED" | "TRADE" | "EXPIRED"; + X: "NEW" | "EXPIRED" | "PARTIALLY_FILLED" | "FILLED" | "CANCELLED" | "PENDING_CANCEL" | "REJECTED"; + r: string; + i: t.Branded; + l: string; + z: string; + L: string; + n: string; + N: null; + T: t.Branded; + t: t.Branded; + I: t.Branded; + w: boolean; + m: boolean; + M: boolean; + O: t.Branded; + Z: string; + Y: string; + Q: string; + } | { + e: "listStatus"; + E: t.Branded; + s: string; + g: t.Branded; + c: "OCO"; + l: "RESPONSE" | "EXEC_STARTED" | "ALL_DONE"; + L: "ALL_DONE" | "EXECUTING" | "REJECT"; + r: string; + C: string; + T: t.Branded; + O: { + s: string; + i: t.Branded; + c: string; + }[]; + }>>; +}; +export {}; diff --git a/dist/binance/core.js b/dist/binance/core.js new file mode 100644 index 0000000..a96b75b --- /dev/null +++ b/dist/binance/core.js @@ -0,0 +1,124 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.makeBinanceWebsocketClient = exports.makeWebsocketStream = exports.makeBinanceHttpClient = exports.fromPromiseToStream = exports.makeSignQuery = exports.buildQueryString = void 0; +const crypto = __importStar(require("crypto")); +const axios_1 = __importDefault(require("axios")); +const function_1 = require("fp-ts/lib/function"); +const fp_ts_1 = require("fp-ts"); +const t = __importStar(require("io-ts")); +const reconnecting_websocket_1 = __importDefault(require("reconnecting-websocket")); +const rxjs_1 = require("rxjs"); +const rxo = __importStar(require("rxjs/operators")); +const Json_1 = require("fp-ts/lib/Json"); +const socketTypes_1 = require("./socketTypes"); +const fp_ts_rxjs_1 = require("fp-ts-rxjs"); +const query_string_1 = __importDefault(require("query-string")); +// refer to binance-node-connector +/** + * NOTE: The array conversion logic is different from usual query string. + * E.g. symbols=["BTCUSDT","BNBBTC"] instead of symbols[]=BTCUSDT&symbols[]=BNBBTC + */ +const stringifyKeyValuePair = ([key, value]) => { + const valueString = Array.isArray(value) ? `["${value.join('","')}"]` : value; + return `${key}=${encodeURIComponent(valueString)}`; +}; +exports.buildQueryString = (0, function_1.flow)(Object.entries, fp_ts_1.array.filter(([_, value]) => (isOption(value) ? fp_ts_1.option.isSome(value) : true)), fp_ts_1.array.map(([key, value]) => fp_ts_1.option.isSome(value) ? [key, value.value] : [key, value]), fp_ts_1.array.map(stringifyKeyValuePair), (kv) => kv.join('&')); +const isOption = (input) => fp_ts_1.option.isNone(input) || fp_ts_1.option.isSome(input); +// the whole query is stored in signature field in order to make it a single source of truth +// otherwise it is required to sign the query twice - once on the user side and then again in the client callback(`request` function) +const makeSignQuery = (apiSecret) => (query) => { + const timestamp = Date.now(); + const queryString = (0, exports.buildQueryString)(Object.assign(Object.assign({}, query), { timestamp })); + const signature = crypto + .createHmac('sha256', apiSecret) + .update(queryString) + .digest('hex'); + return Object.assign(Object.assign({}, query), { timestamp: timestamp, signature: `${queryString}&signature=${signature}` }); +}; +exports.makeSignQuery = makeSignQuery; +const getBinanceUrl = (url, rawQuery) => rawQuery === undefined + ? url + : (0, function_1.pipe)(rawQuery, query_string_1.default.parse, (query) => query['signature'] + ? query['signature'] + : (0, exports.buildQueryString)(query), (binanceQuery) => `${url}?${binanceQuery}`); +const fromPromiseToStream = (promise) => new rxjs_1.Observable((subscriber) => { + promise() + .then((value) => { + if (!subscriber.closed) { + subscriber.next(fp_ts_1.either.right(value)); + subscriber.complete(); + } + }) + .catch((e) => subscriber.next(fp_ts_1.either.left(e))); +}); +exports.fromPromiseToStream = fromPromiseToStream; +const makeBinanceHttpClient = (baseURL, config) => ({ + signQuery: (0, exports.makeSignQuery)(config.apiSecret), + httpClient: Object.assign(Object.assign({}, fp_ts_rxjs_1.observableEither.observableEither), { request: (request) => { + const { method, query: rawQueryString, url: rawUrl } = request; + const url = getBinanceUrl(rawUrl, rawQueryString); + const instance = axios_1.default.create({ + baseURL, + headers: { + 'Content-Type': 'application/json', + 'X-MBX-APIKEY': config.apiKey, + }, + }); + instance.interceptors.response.use((r) => r, (error) => Promise.reject(error.response.data)); + return (0, function_1.pipe)(() => instance.request({ + method, + url, + }), exports.fromPromiseToStream, rxo.map(fp_ts_1.either.bimap((e) => new Error(String(e)), (response) => response.data))); + } }), +}); +exports.makeBinanceHttpClient = makeBinanceHttpClient; +const makeWebsocketStream = (url, websocketImplementation) => { + const subject = new rxjs_1.Subject(); + const websocket = new reconnecting_websocket_1.default(url, undefined, { + debug: true, + minReconnectionDelay: 3000, + WebSocket: websocketImplementation, + }); + websocket.addEventListener('message', (e) => subject.next((0, function_1.pipe)((0, Json_1.parse)(e.data), fp_ts_1.either.mapLeft((e) => new Error(String(e)))))); + return subject.asObservable(); +}; +exports.makeWebsocketStream = makeWebsocketStream; +const fromWebsocketStream = (stream$, parser) => (0, function_1.pipe)(stream$, rxo.map(fp_ts_1.either.chain((0, function_1.flow)(parser, fp_ts_1.either.mapLeft((e) => new Error(JSON.stringify(e.map((e) => e.context)))))))); +// based on binance-connector +const makeBinanceWebsocketClient = (baseURL, websocketImplementation) => ({ + aggregatedTrade: (symbol) => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/${symbol.toLowerCase()}@aggTrade`, websocketImplementation), socketTypes_1.BinanceSocketAggregatedTradeIO.decode), + trade: (symbol) => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/${symbol.toLowerCase()}@trade`, websocketImplementation), socketTypes_1.BinanceSocketTradeIO.decode), + kline: (symbol, interval) => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/${symbol.toLowerCase()}@kline_${interval}`, websocketImplementation), socketTypes_1.BinanceSocketKlineIO.decode), + miniTicker: (symbol) => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/${symbol.toLowerCase()}@miniTicker`, websocketImplementation), socketTypes_1.BinanceSocketMiniTickerIO.decode), + miniTickers: () => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/!miniTicker@arr`, websocketImplementation), t.array(socketTypes_1.BinanceSocketMiniTickerIO).decode), + ticker: (symbol) => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/${symbol.toLowerCase()}@ticker`, websocketImplementation), socketTypes_1.BinanceSocketTickerIO.decode), + tickers: () => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/!ticker@arr`, websocketImplementation), t.array(socketTypes_1.BinanceSocketTickerIO).decode), + bookTicker: (symbol) => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/${symbol.toLowerCase()}@bookTicker`, websocketImplementation), socketTypes_1.BinanceSocketBookTickerIO.decode), + bookTickers: () => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/!bookTicker`, websocketImplementation), socketTypes_1.BinanceSocketBookTickerIO.decode), + partialBookDepth: (symbol, levels, speed) => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/${symbol.toLowerCase()}@depth${levels}@${speed}`, websocketImplementation), socketTypes_1.BinanceSocketPartialBookDepthIO.decode), + diffBookDepth: (symbol, speed) => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/${symbol.toLowerCase()}@depth@${speed}`, websocketImplementation), socketTypes_1.BinanceSocketDiffDepthIO.decode), + userData: (listenKey) => fromWebsocketStream((0, exports.makeWebsocketStream)(`${baseURL}/ws/${listenKey}`, websocketImplementation), socketTypes_1.BinanceSocketUserUpdateIO.decode), +}); +exports.makeBinanceWebsocketClient = makeBinanceWebsocketClient; diff --git a/dist/binance/socketTypes.d.ts b/dist/binance/socketTypes.d.ts new file mode 100644 index 0000000..4d44105 --- /dev/null +++ b/dist/binance/socketTypes.d.ts @@ -0,0 +1,285 @@ +import * as t from 'io-ts'; +export declare const BinanceSocketOrderTypeIO: t.UnionC<[t.LiteralC<"LIMIT">, t.LiteralC<"MARKET">, t.LiteralC<"STOP_LOSS">, t.LiteralC<"STOP_LOSS_LIMIT">, t.LiteralC<"TAKE_PROFIT">, t.LiteralC<"TAKE_PROFIT_LIMIT">, t.LiteralC<"LIMIT_MAKER">]>; +export declare type BinanceSocketOrderType = t.TypeOf; +export declare const BinanceSocketSideIO: t.UnionC<[t.LiteralC<"SELL">, t.LiteralC<"BUY">]>; +export declare type BinanceSocketSide = t.TypeOf; +export declare const BinanceTimeInForceIO: t.UnionC<[t.LiteralC<"GTC">, t.LiteralC<"IOC">, t.LiteralC<"FOK">]>; +export declare type BinanceTimeInForce = t.TypeOf; +export declare const BinanceIntervalIO: t.UnionC<[t.LiteralC<"1m">, t.LiteralC<"3m">, t.LiteralC<"5m">, t.LiteralC<"15m">, t.LiteralC<"30m">, t.LiteralC<"1h">, t.LiteralC<"2h">, t.LiteralC<"4h">, t.LiteralC<"6h">, t.LiteralC<"8h">, t.LiteralC<"12h">, t.LiteralC<"1d">, t.LiteralC<"3d">, t.LiteralC<"1w">, t.LiteralC<"1M">]>; +export declare type BinanceInterval = t.TypeOf; +export declare const BinanceOrderResponseIO: t.TypeC<{ + symbol: t.StringC; + orderId: t.NumberC; + clientOrderId: t.StringC; + transactTime: t.NumberC; + price: t.StringC; + origQty: t.StringC; + executedQty: t.StringC; + status: t.StringC; + timeInForce: t.StringC; + type: t.StringC; + side: t.StringC; +}>; +export declare type BinanceOrderResponse = t.TypeOf; +export declare const BinanceSocketAggregatedTradeIO: t.TypeC<{ + e: t.LiteralC<"aggTrade">; + E: t.BrandC; + s: t.StringC; + a: t.BrandC; + p: t.StringC; + q: t.StringC; + f: t.BrandC; + l: t.BrandC; + T: t.BrandC; + m: t.BooleanC; + M: t.BooleanC; +}>; +export declare type BinanceSocketAggregatedTrade = t.TypeOf; +export declare const BinanceSocketTradeIO: t.TypeC<{ + e: t.LiteralC<"trade">; + E: t.BrandC; + s: t.StringC; + t: t.BrandC; + p: t.StringC; + q: t.StringC; + b: t.BrandC; + a: t.BrandC; + T: t.BrandC; + m: t.BooleanC; + M: t.BooleanC; +}>; +export declare type BinanceSocketTrade = t.TypeOf; +export declare const BinanceSocketKlineIO: t.TypeC<{ + e: t.LiteralC<"kline">; + E: t.NumberC; + s: t.StringC; + k: t.TypeC<{ + t: t.NumberC; + T: t.NumberC; + s: t.StringC; + i: t.UnionC<[t.LiteralC<"1m">, t.LiteralC<"3m">, t.LiteralC<"5m">, t.LiteralC<"15m">, t.LiteralC<"30m">, t.LiteralC<"1h">, t.LiteralC<"2h">, t.LiteralC<"4h">, t.LiteralC<"6h">, t.LiteralC<"8h">, t.LiteralC<"12h">, t.LiteralC<"1d">, t.LiteralC<"3d">, t.LiteralC<"1w">, t.LiteralC<"1M">]>; + f: t.NumberC; + L: t.NumberC; + o: t.StringC; + c: t.StringC; + h: t.StringC; + l: t.StringC; + v: t.StringC; + n: t.NumberC; + x: t.BooleanC; + q: t.StringC; + V: t.StringC; + Q: t.StringC; + B: t.StringC; + }>; +}>; +export declare type BinanceSocketKline = t.TypeOf; +export declare const BinanceSocketMiniTickerIO: t.TypeC<{ + e: t.LiteralC<"24hrMiniTicker">; + E: t.BrandC; + s: t.StringC; + c: t.StringC; + o: t.StringC; + h: t.StringC; + l: t.StringC; + v: t.StringC; + q: t.StringC; +}>; +export declare type BinanceSocketMiniTicker = t.TypeOf; +export declare const BinanceSocketTickerIO: t.TypeC<{ + e: t.LiteralC<"24hrTicker">; + E: t.BrandC; + s: t.StringC; + p: t.StringC; + P: t.StringC; + w: t.StringC; + x: t.StringC; + c: t.StringC; + Q: t.StringC; + b: t.StringC; + B: t.StringC; + a: t.StringC; + A: t.StringC; + o: t.StringC; + h: t.StringC; + l: t.StringC; + v: t.StringC; + q: t.StringC; + O: t.BrandC; + C: t.BrandC; + F: t.BrandC; + L: t.BrandC; + n: t.BrandC; +}>; +export declare type BinanceSocketTicker = t.TypeOf; +export declare const BinanceSocketBookTickerIO: t.TypeC<{ + u: t.BrandC; + s: t.StringC; + b: t.StringC; + B: t.StringC; + a: t.StringC; + A: t.StringC; +}>; +export declare type BinanceSocketBookTicker = t.TypeOf; +export declare const BinanceSocketPartialBookDepthIO: t.TypeC<{ + lastUpdateId: t.BrandC; + bids: t.ArrayC>; + asks: t.ArrayC>; +}>; +export declare type BinanceSocketPartialBookDepth = t.TypeOf; +export declare const BinanceSocketDiffDepthIO: t.TypeC<{ + e: t.LiteralC<"depthUpdate">; + E: t.BrandC; + s: t.StringC; + U: t.BrandC; + u: t.BrandC; + b: t.ArrayC>; + a: t.ArrayC>; +}>; +export declare type BinanceSocketDiffDepth = t.TypeOf; +export declare const BinanceSocketAccountUpdateIO: t.TypeC<{ + e: t.LiteralC<"outboundAccountPosition">; + E: t.BrandC; + u: t.BrandC; + B: t.ArrayC>; +}>; +export declare type BinanceSocketAccountUpdate = t.TypeOf; +export declare const BinanceSocketBalanceUpdateIO: t.TypeC<{ + e: t.LiteralC<"balanceUpdate">; + E: t.BrandC; + a: t.StringC; + d: t.StringC; + T: t.BrandC; +}>; +export declare type BinanceSocketBalanceUpdate = t.TypeOf; +export declare const BinanceSocketExecutionTypeIO: t.UnionC<[t.LiteralC<"NEW">, t.LiteralC<"CANCELED">, t.LiteralC<"REPLACED">, t.LiteralC<"TRADE">, t.LiteralC<"EXPIRED">]>; +export declare type BinanceSocketExecutionType = t.TypeOf; +export declare const BinanceSocketOrderStatusIO: t.UnionC<[t.LiteralC<"NEW">, t.LiteralC<"PARTIALLY_FILLED">, t.LiteralC<"FILLED">, t.LiteralC<"CANCELLED">, t.LiteralC<"PENDING_CANCEL">, t.LiteralC<"REJECTED">, t.LiteralC<"EXPIRED">]>; +export declare type BinanceSocketOrderStatus = t.TypeOf; +export declare const BinanceSocketOrderUpdateIO: t.TypeC<{ + e: t.LiteralC<"executionReport">; + E: t.BrandC; + s: t.StringC; + c: t.StringC; + S: t.UnionC<[t.LiteralC<"SELL">, t.LiteralC<"BUY">]>; + o: t.UnionC<[t.LiteralC<"LIMIT">, t.LiteralC<"MARKET">, t.LiteralC<"STOP_LOSS">, t.LiteralC<"STOP_LOSS_LIMIT">, t.LiteralC<"TAKE_PROFIT">, t.LiteralC<"TAKE_PROFIT_LIMIT">, t.LiteralC<"LIMIT_MAKER">]>; + f: t.UnionC<[t.LiteralC<"GTC">, t.LiteralC<"IOC">, t.LiteralC<"FOK">]>; + q: t.StringC; + p: t.StringC; + P: t.StringC; + F: t.StringC; + g: t.BrandC; + C: t.StringC; + x: t.UnionC<[t.LiteralC<"NEW">, t.LiteralC<"CANCELED">, t.LiteralC<"REPLACED">, t.LiteralC<"TRADE">, t.LiteralC<"EXPIRED">]>; + X: t.UnionC<[t.LiteralC<"NEW">, t.LiteralC<"PARTIALLY_FILLED">, t.LiteralC<"FILLED">, t.LiteralC<"CANCELLED">, t.LiteralC<"PENDING_CANCEL">, t.LiteralC<"REJECTED">, t.LiteralC<"EXPIRED">]>; + r: t.StringC; + i: t.BrandC; + l: t.StringC; + z: t.StringC; + L: t.StringC; + n: t.StringC; + N: t.NullC; + T: t.BrandC; + t: t.BrandC; + I: t.BrandC; + w: t.BooleanC; + m: t.BooleanC; + M: t.BooleanC; + O: t.BrandC; + Z: t.StringC; + Y: t.StringC; + Q: t.StringC; +}>; +export declare type BinanceSocketOrderUpdate = t.TypeOf; +export declare const BinanceSocketOCOListStatusIO: t.UnionC<[t.LiteralC<"RESPONSE">, t.LiteralC<"EXEC_STARTED">, t.LiteralC<"ALL_DONE">]>; +export declare type BinanceSocketOCOListStatus = t.TypeOf; +export declare const BinanceSocketOCOListOrderStatusIO: t.UnionC<[t.LiteralC<"EXECUTING">, t.LiteralC<"ALL_DONE">, t.LiteralC<"REJECT">]>; +export declare type BinanceSocketOCOListOrderStatus = t.TypeOf; +export declare const BinanceSocketListStatusIO: t.TypeC<{ + e: t.LiteralC<"listStatus">; + E: t.BrandC; + s: t.StringC; + g: t.BrandC; + c: t.LiteralC<"OCO">; + l: t.UnionC<[t.LiteralC<"RESPONSE">, t.LiteralC<"EXEC_STARTED">, t.LiteralC<"ALL_DONE">]>; + L: t.UnionC<[t.LiteralC<"EXECUTING">, t.LiteralC<"ALL_DONE">, t.LiteralC<"REJECT">]>; + r: t.StringC; + C: t.StringC; + T: t.BrandC; + O: t.ArrayC; + c: t.StringC; + }>>; +}>; +export declare type BinanceSocketListStatus = t.TypeOf; +export declare const BinanceSocketUserUpdateIO: t.UnionC<[t.TypeC<{ + e: t.LiteralC<"outboundAccountPosition">; + E: t.BrandC; + u: t.BrandC; + B: t.ArrayC>; +}>, t.TypeC<{ + e: t.LiteralC<"balanceUpdate">; + E: t.BrandC; + a: t.StringC; + d: t.StringC; + T: t.BrandC; +}>, t.TypeC<{ + e: t.LiteralC<"executionReport">; + E: t.BrandC; + s: t.StringC; + c: t.StringC; + S: t.UnionC<[t.LiteralC<"SELL">, t.LiteralC<"BUY">]>; + o: t.UnionC<[t.LiteralC<"LIMIT">, t.LiteralC<"MARKET">, t.LiteralC<"STOP_LOSS">, t.LiteralC<"STOP_LOSS_LIMIT">, t.LiteralC<"TAKE_PROFIT">, t.LiteralC<"TAKE_PROFIT_LIMIT">, t.LiteralC<"LIMIT_MAKER">]>; + f: t.UnionC<[t.LiteralC<"GTC">, t.LiteralC<"IOC">, t.LiteralC<"FOK">]>; + q: t.StringC; + p: t.StringC; + P: t.StringC; + F: t.StringC; + g: t.BrandC; + C: t.StringC; + x: t.UnionC<[t.LiteralC<"NEW">, t.LiteralC<"CANCELED">, t.LiteralC<"REPLACED">, t.LiteralC<"TRADE">, t.LiteralC<"EXPIRED">]>; + X: t.UnionC<[t.LiteralC<"NEW">, t.LiteralC<"PARTIALLY_FILLED">, t.LiteralC<"FILLED">, t.LiteralC<"CANCELLED">, t.LiteralC<"PENDING_CANCEL">, t.LiteralC<"REJECTED">, t.LiteralC<"EXPIRED">]>; + r: t.StringC; + i: t.BrandC; + l: t.StringC; + z: t.StringC; + L: t.StringC; + n: t.StringC; + N: t.NullC; + T: t.BrandC; + t: t.BrandC; + I: t.BrandC; + w: t.BooleanC; + m: t.BooleanC; + M: t.BooleanC; + O: t.BrandC; + Z: t.StringC; + Y: t.StringC; + Q: t.StringC; +}>, t.TypeC<{ + e: t.LiteralC<"listStatus">; + E: t.BrandC; + s: t.StringC; + g: t.BrandC; + c: t.LiteralC<"OCO">; + l: t.UnionC<[t.LiteralC<"RESPONSE">, t.LiteralC<"EXEC_STARTED">, t.LiteralC<"ALL_DONE">]>; + L: t.UnionC<[t.LiteralC<"EXECUTING">, t.LiteralC<"ALL_DONE">, t.LiteralC<"REJECT">]>; + r: t.StringC; + C: t.StringC; + T: t.BrandC; + O: t.ArrayC; + c: t.StringC; + }>>; +}>]>; +export declare type BinanceSocketUserUpdate = t.TypeOf; diff --git a/dist/binance/socketTypes.js b/dist/binance/socketTypes.js new file mode 100644 index 0000000..92f48e5 --- /dev/null +++ b/dist/binance/socketTypes.js @@ -0,0 +1,282 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BinanceSocketUserUpdateIO = exports.BinanceSocketListStatusIO = exports.BinanceSocketOCOListOrderStatusIO = exports.BinanceSocketOCOListStatusIO = exports.BinanceSocketOrderUpdateIO = exports.BinanceSocketOrderStatusIO = exports.BinanceSocketExecutionTypeIO = exports.BinanceSocketBalanceUpdateIO = exports.BinanceSocketAccountUpdateIO = exports.BinanceSocketDiffDepthIO = exports.BinanceSocketPartialBookDepthIO = exports.BinanceSocketBookTickerIO = exports.BinanceSocketTickerIO = exports.BinanceSocketMiniTickerIO = exports.BinanceSocketKlineIO = exports.BinanceSocketTradeIO = exports.BinanceSocketAggregatedTradeIO = exports.BinanceOrderResponseIO = exports.BinanceIntervalIO = exports.BinanceTimeInForceIO = exports.BinanceSocketSideIO = exports.BinanceSocketOrderTypeIO = void 0; +const t = __importStar(require("io-ts")); +exports.BinanceSocketOrderTypeIO = t.union([ + t.literal('LIMIT'), + t.literal('MARKET'), + t.literal('STOP_LOSS'), + t.literal('STOP_LOSS_LIMIT'), + t.literal('TAKE_PROFIT'), + t.literal('TAKE_PROFIT_LIMIT'), + t.literal('LIMIT_MAKER'), +]); +exports.BinanceSocketSideIO = t.union([ + t.literal('SELL'), + t.literal('BUY'), +]); +exports.BinanceTimeInForceIO = t.union([ + t.literal('GTC'), + t.literal('IOC'), + t.literal('FOK'), +]); +exports.BinanceIntervalIO = t.union([ + t.literal('1m'), + t.literal('3m'), + t.literal('5m'), + t.literal('15m'), + t.literal('30m'), + t.literal('1h'), + t.literal('2h'), + t.literal('4h'), + t.literal('6h'), + t.literal('8h'), + t.literal('12h'), + t.literal('1d'), + t.literal('3d'), + t.literal('1w'), + t.literal('1M'), +]); +exports.BinanceOrderResponseIO = t.type({ + symbol: t.string, + orderId: t.number, + clientOrderId: t.string, + transactTime: t.number, + price: t.string, + origQty: t.string, + executedQty: t.string, + status: t.string, + timeInForce: t.string, + type: t.string, + side: t.string, +}); +// websocket +exports.BinanceSocketAggregatedTradeIO = t.type({ + e: t.literal('aggTrade'), + E: t.Int, + s: t.string, + a: t.Int, + p: t.string, + q: t.string, + f: t.Int, + l: t.Int, + T: t.Int, + m: t.boolean, + M: t.boolean, // Ignore +}); +exports.BinanceSocketTradeIO = t.type({ + e: t.literal('trade'), + E: t.Int, + s: t.string, + t: t.Int, + p: t.string, + q: t.string, + b: t.Int, + a: t.Int, + T: t.Int, + m: t.boolean, + M: t.boolean, // Ignore +}); +exports.BinanceSocketKlineIO = t.type({ + e: t.literal('kline'), + E: t.number, + s: t.string, + k: t.type({ + t: t.number, + T: t.number, + s: t.string, + i: exports.BinanceIntervalIO, + f: t.number, + L: t.number, + o: t.string, + c: t.string, + h: t.string, + l: t.string, + v: t.string, + n: t.number, + x: t.boolean, + q: t.string, + V: t.string, + Q: t.string, + B: t.string, // Ignore + }), +}); +exports.BinanceSocketMiniTickerIO = t.type({ + e: t.literal('24hrMiniTicker'), + E: t.Int, + s: t.string, + c: t.string, + o: t.string, + h: t.string, + l: t.string, + v: t.string, + q: t.string, // Total traded quote asset volume +}); +exports.BinanceSocketTickerIO = t.type({ + e: t.literal('24hrTicker'), + E: t.Int, + s: t.string, + p: t.string, + P: t.string, + w: t.string, + x: t.string, + c: t.string, + Q: t.string, + b: t.string, + B: t.string, + a: t.string, + A: t.string, + o: t.string, + h: t.string, + l: t.string, + v: t.string, + q: t.string, + O: t.Int, + C: t.Int, + F: t.Int, + L: t.Int, + n: t.Int, // Total number of trades +}); +exports.BinanceSocketBookTickerIO = t.type({ + u: t.Int, + s: t.string, + b: t.string, + B: t.string, + a: t.string, + A: t.string, // best ask qty +}); +exports.BinanceSocketPartialBookDepthIO = t.type({ + lastUpdateId: t.Int, + bids: t.array(t.tuple([t.string, t.string])), + asks: t.array(t.tuple([t.string, t.string])), // [Price level to be updated, Quantity][] +}); +exports.BinanceSocketDiffDepthIO = t.type({ + e: t.literal('depthUpdate'), + E: t.Int, + s: t.string, + U: t.Int, + u: t.Int, + b: t.array(t.tuple([t.string, t.string])), + a: t.array(t.tuple([t.string, t.string])), // [Price level to be updated, Quantity][] +}); +exports.BinanceSocketAccountUpdateIO = t.type({ + e: t.literal('outboundAccountPosition'), + E: t.Int, + u: t.Int, + B: + //Balances Array + t.array(t.type({ + a: t.string, + f: t.string, + l: t.string, //Locked + })), +}); +exports.BinanceSocketBalanceUpdateIO = t.type({ + e: t.literal('balanceUpdate'), + E: t.Int, + a: t.string, + d: t.string, + T: t.Int, //Clear Time +}); +exports.BinanceSocketExecutionTypeIO = t.union([ + t.literal('NEW'), + t.literal('CANCELED'), + t.literal('REPLACED'), + t.literal('TRADE'), + t.literal('EXPIRED'), +]); +exports.BinanceSocketOrderStatusIO = t.union([ + t.literal('NEW'), + t.literal('PARTIALLY_FILLED'), + t.literal('FILLED'), + t.literal('CANCELLED'), + t.literal('PENDING_CANCEL'), + t.literal('REJECTED'), + t.literal('EXPIRED'), +]); +exports.BinanceSocketOrderUpdateIO = t.type({ + e: t.literal('executionReport'), + E: t.Int, + s: t.string, + c: t.string, + S: exports.BinanceSocketSideIO, + o: exports.BinanceSocketOrderTypeIO, + f: exports.BinanceTimeInForceIO, + q: t.string, + p: t.string, + P: t.string, + F: t.string, + g: t.Int, + C: t.string, + x: exports.BinanceSocketExecutionTypeIO, + X: exports.BinanceSocketOrderStatusIO, + r: t.string, + i: t.Int, + l: t.string, + z: t.string, + L: t.string, + n: t.string, + N: t.null, + T: t.Int, + t: t.Int, + I: t.Int, + w: t.boolean, + m: t.boolean, + M: t.boolean, + O: t.Int, + Z: t.string, + Y: t.string, + Q: t.string, // Quote Order Qty +}); +exports.BinanceSocketOCOListStatusIO = t.union([ + t.literal('RESPONSE'), + t.literal('EXEC_STARTED'), + t.literal('ALL_DONE'), +]); +exports.BinanceSocketOCOListOrderStatusIO = t.union([ + t.literal('EXECUTING'), + t.literal('ALL_DONE'), + t.literal('REJECT'), +]); +exports.BinanceSocketListStatusIO = t.type({ + e: t.literal('listStatus'), + E: t.Int, + s: t.string, + g: t.Int, + c: t.literal('OCO'), + l: exports.BinanceSocketOCOListStatusIO, + L: exports.BinanceSocketOCOListOrderStatusIO, + r: t.string, + C: t.string, + T: t.Int, + O: t.array(t.type({ + s: t.string, + i: t.Int, + c: t.string, //ClientOrderId + })), +}); +exports.BinanceSocketUserUpdateIO = t.union([ + exports.BinanceSocketAccountUpdateIO, + exports.BinanceSocketBalanceUpdateIO, + exports.BinanceSocketOrderUpdateIO, + exports.BinanceSocketListStatusIO, +]); diff --git a/dist/generate.d.ts b/dist/generate.d.ts new file mode 100644 index 0000000..c1437c5 --- /dev/null +++ b/dist/generate.d.ts @@ -0,0 +1,4 @@ +/// +import { taskEither } from 'fp-ts'; +export declare const generateApifromFile: (baseDir: string, specPath: string, out: string) => taskEither.TaskEither; +export declare const generateApifromURL: (baseDir: string, specUrl: string, out: string) => taskEither.TaskEither; diff --git a/dist/generate.js b/dist/generate.js new file mode 100644 index 0000000..dfd1762 --- /dev/null +++ b/dist/generate.js @@ -0,0 +1,66 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generateApifromURL = exports.generateApifromFile = void 0; +const swagger_codegen_ts_1 = require("@devexperts/swagger-codegen-ts"); +const path = __importStar(require("path")); +const _3_0_1 = require("@devexperts/swagger-codegen-ts/dist/language/typescript/3.0"); +const openapi_object_1 = require("@devexperts/swagger-codegen-ts/dist/schema/3.0/openapi-object"); +const fp_ts_1 = require("fp-ts"); +const replace_in_file_1 = require("replace-in-file"); +const function_1 = require("fp-ts/lib/function"); +const axios_1 = __importDefault(require("axios")); +const fs_1 = __importDefault(require("fs")); +const util_1 = require("util"); +// api has a parameter called 'symbol', which conflicts with js' native type +const fixSymbolType = (glob) => (0, replace_in_file_1.replaceInFile)({ + files: glob, + from: [ + 'export type symbol = string;', + 'export const symbolIO = string;', + new RegExp(`import { symbol, symbolIO } from '../components/parameters/symbol';`, 'g'), + new RegExp('symbol: symbol', 'g'), + new RegExp('symbolIO.', 'g'), + ], + to: [ + 'export type tickerSymbol = string;', + 'export const tickerSymbolIO = string;', + "import { tickerSymbol, tickerSymbolIO } from '../components/parameters/symbol';", + 'symbol: tickerSymbol', + 'tickerSymbolIO.', + ], +}); +const generateApifromFile = (baseDir, specPath, out) => (0, function_1.pipe)((0, swagger_codegen_ts_1.generate)({ + cwd: baseDir, + spec: path.resolve(baseDir, specPath), + out: path.resolve(baseDir, out), + language: _3_0_1.serialize, + decoder: openapi_object_1.OpenapiObjectCodec, +}), fp_ts_1.taskEither.chain(() => fp_ts_1.taskEither.tryCatch(() => fixSymbolType(`${path.resolve(baseDir, out)}/spot_api.yaml/**/*.ts`), function_1.identity))); +exports.generateApifromFile = generateApifromFile; +const generateApifromURL = (baseDir, specUrl, out) => (0, function_1.pipe)(fp_ts_1.taskEither.tryCatch(() => axios_1.default.get(specUrl), function_1.identity), fp_ts_1.taskEither.chain((response) => fp_ts_1.taskEither.tryCatch(() => (0, util_1.promisify)(fs_1.default.writeFile)('spot_api.yaml', response.data), function_1.identity)), fp_ts_1.taskEither.chain(() => (0, exports.generateApifromFile)(baseDir, 'spot_api.yaml', out)), fp_ts_1.taskEither.chain(() => fp_ts_1.taskEither.tryCatch(() => (0, util_1.promisify)(fs_1.default.unlink)('spot_api.yaml'), (e) => { + console.log('Failed to cleanup'); + return e; +}))); +exports.generateApifromURL = generateApifromURL; diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..af1ace4 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,4 @@ +export * from './binance/core'; +export * from './binance/socketTypes'; +export * from './binance/apiTypes'; +export * from './generate'; diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..c5235bf --- /dev/null +++ b/dist/index.js @@ -0,0 +1,16 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./binance/core"), exports); +__exportStar(require("./binance/socketTypes"), exports); +__exportStar(require("./binance/apiTypes"), exports); +__exportStar(require("./generate"), exports); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..828aa24 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,910 @@ +{ + "name": "binance-api", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@devexperts/swagger-codegen-ts": { + "version": "2.0.0-alpha.27", + "resolved": "https://registry.npmjs.org/@devexperts/swagger-codegen-ts/-/swagger-codegen-ts-2.0.0-alpha.27.tgz", + "integrity": "sha512-zjvv2RXu9vL8P26cN2oDeWV4M8G0IP67VEy8gzQpmEe3+qm1YKFgxtsjaWBoXDgUSdqrWsmESJ4RE1X6qdqWnA==", + "requires": { + "@devexperts/utils": "^1.0.0-alpha.10", + "@types/adm-zip": "^0.4.32", + "@types/color": "^3.0.0", + "@types/fs-extra": "^8.0.0", + "@types/prettier": "^1.13.2", + "adm-zip": "^0.4.13", + "color": "^3.1.2", + "eslint-plugin-prettier": "^3.1.1", + "fs-extra": "^8.1.0", + "json-schema-ref-parser": "^7.1.1", + "prettier": "^1.19.1" + }, + "dependencies": { + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==" + } + } + }, + "@devexperts/utils": { + "version": "1.0.0-alpha.14", + "resolved": "https://registry.npmjs.org/@devexperts/utils/-/utils-1.0.0-alpha.14.tgz", + "integrity": "sha512-dYpaGgSJ3+KtmBdJI0m+mIxzW+aKyl4WiQD+xSnX0zngE0g5Nf8GICQJE6lze67XL0i+TlbS9DmTR1qvwNwarw==", + "requires": { + "tslib": "^1.10.0", + "typelevel-ts": "^0.3.5" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@types/adm-zip": { + "version": "0.4.34", + "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.4.34.tgz", + "integrity": "sha512-8ToYLLAYhkRfcmmljrKi22gT2pqu7hGMDtORP1emwIEGmgUTZOsaDjzWFzW5N2frcFRz/50CWt4zA1CxJ73pmQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/color": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.2.tgz", + "integrity": "sha512-INiJl6sfNn8iyC5paxVzqiVUEj2boIlFki02uRTAkKwAj++7aAF+ZfEv/XrIeBa0XI/fTZuDHW8rEEcEVnON+Q==", + "requires": { + "@types/color-convert": "*" + } + }, + "@types/color-convert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.0.tgz", + "integrity": "sha512-m7GG7IKKGuJUXvkZ1qqG3ChccdIM/qBBo913z+Xft0nKCX4hAU/IxKwZBU4cpRZ7GS5kV4vOblUkILtSShCPXQ==", + "requires": { + "@types/color-name": "*" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "@types/fs-extra": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz", + "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "16.9.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.5.tgz", + "integrity": "sha512-5xkJln5CDkmQTi13oWS+EUruKbfHJD5CQnyxe8L3Gt3sLsPFl+rjiOVU7O59QF1RUyw3rdkm9yDTNQcOR+ob9A==" + }, + "@types/prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==" + }, + "@types/query-string": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@types/query-string/-/query-string-6.3.0.tgz", + "integrity": "sha512-yuIv/WRffRzL7cBW+sla4HwBZrEXRNf1MKQ5SklPEadth+BKbDxiVG8A3iISN5B3yC4EeSCzMZP8llHTcUhOzQ==", + "dev": true, + "requires": { + "query-string": "*" + } + }, + "@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=", + "dev": true + }, + "@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true + }, + "adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==" + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "requires": { + "follow-redirects": "^1.14.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + }, + "dependencies": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + } + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "color-string": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", + "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=", + "dev": true, + "requires": { + "xtend": "^4.0.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "eslint-plugin-prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=" + }, + "follow-redirects": { + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", + "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==" + }, + "fp-ts": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.11.4.tgz", + "integrity": "sha512-lhV7tGEbs2qoVw4vmqOovChS7CAoIYU0gdiPEF8Vc4bLZct+PAMMeXrCqRyBNEo33XOvwvAmFDEDIrHPWH2/fg==", + "dev": true + }, + "fp-ts-rxjs": { + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/fp-ts-rxjs/-/fp-ts-rxjs-0.6.15.tgz", + "integrity": "sha512-5fD4a/439l0aUkSkPq7xnznXYsD7YwGyYANO3v6dkkZJTta36et3bNJ2tzq28UcVR6bS9nTDbP7kMjgQqFFxYQ==" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "io-ts": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.16.tgz", + "integrity": "sha512-y5TTSa6VP6le0hhmIyN0dqEXkrZeJLeC5KApJq6VLci3UEKF80lZ+KuoUs02RhBxNWlrqSNxzfI7otLX1Euv8Q==", + "dev": true + }, + "io-ts-types": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/io-ts-types/-/io-ts-types-0.5.16.tgz", + "integrity": "sha512-h9noYVfY9rlbmKI902SJdnV/06jgiT2chxG6lYDxaYNp88HscPi+SBCtmcU+m0E7WT5QSwt7sIMj93+qu0FEwQ==", + "dev": true + }, + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "json-schema-ref-parser": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-7.1.4.tgz", + "integrity": "sha512-AD7bvav0vak1/63w3jH8F7eHId/4E4EPdMAEZhGxtjktteUv9dnNB/cJy6nVnMyoTPBJnLwFK6tiQPSTeleCtQ==", + "requires": { + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.13.1", + "ono": "^6.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "ono": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ono/-/ono-6.0.1.tgz", + "integrity": "sha512-5rdYW/106kHqLeG22GE2MHKq+FlsxMERZev9DCzQX1zwkxnFwBivSn5i17a5O/rDmOJOdf4Wyt80UZljzx9+DA==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "prettier": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", + "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "requires": { + "fast-diff": "^1.1.2" + } + }, + "query-string": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.0.1.tgz", + "integrity": "sha512-uIw3iRvHnk9to1blJCG3BTc+Ro56CBowJXKmNNAm3RulvPBzWLRqKSiiDk+IplJhsydwtuNMHi8UGQFcCLVfkA==", + "requires": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "reconnecting-websocket": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz", + "integrity": "sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==" + }, + "replace-in-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.2.0.tgz", + "integrity": "sha512-Im2AF9G/qgkYneOc9QwWwUS/efyyonTUBvzXS2VXuxPawE5yQIjT/e6x4CTijO0Quq48lfAujuo+S89RR2TP2Q==", + "requires": { + "chalk": "^4.1.0", + "glob": "^7.1.6", + "yargs": "^16.2.0" + }, + "dependencies": { + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rxjs": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.3.0.tgz", + "integrity": "sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw==", + "dev": true, + "requires": { + "tslib": "~2.1.0" + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", + "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "ts-node": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", + "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, + "ts-node-dev": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.1.8.tgz", + "integrity": "sha512-Q/m3vEwzYwLZKmV6/0VlFxcZzVV/xcgOt+Tx/VjaaRHyiBcFlV0541yrT09QjzzCxlDZ34OzKjrFAynlmtflEg==", + "dev": true, + "requires": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.5", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^9.0.0", + "tsconfig": "^7.0.0" + } + }, + "tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "requires": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + }, + "typelevel-ts": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/typelevel-ts/-/typelevel-ts-0.3.5.tgz", + "integrity": "sha512-VZKF0ak5RNgrPkpI2uJJL0WBqNcj67+hzYzD6SwoxzrgvgjP24gskqniXd62UY5rrJCxd3q/iChtxKcHC6fRvA==" + }, + "typescript": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", + "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..fc4aac0 --- /dev/null +++ b/package.json @@ -0,0 +1,46 @@ +{ + "name": "binance-typescript-api", + "version": "1.0.0", + "description": "", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*" + ], + "scripts": { + "build": "tsc", + "test": "echo \"Error: no test specified\" && exit 1", + "prettify": "prettier --write src/**/*.{ts,tsx,js,jsx,css,scss,json}", + "dev": "ts-node-dev src/app.ts", + "check-types": "tsc -p . --noEmit", + "check-types:watch": "tsc -p . --noEmit -w" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@types/node": "^16.9.5", + "@types/query-string": "^6.3.0", + "fp-ts": "^2.11.3", + "io-ts": "^2.2.16", + "io-ts-types": "^0.5.16", + "prettier": "^2.4.1", + "rxjs": "^7.3.0", + "ts-node-dev": "^1.1.8", + "typescript": "^4.4.3" + }, + "dependencies": { + "axios": "^0.21.4", + "@devexperts/swagger-codegen-ts": "^2.0.0-alpha.27", + "fp-ts-rxjs": "^0.6.15", + "query-string": "^7.0.1", + "reconnecting-websocket": "^4.4.0", + "replace-in-file": "^6.2.0" + }, + "peerDependencies": { + "typescript": "^4.4.3", + "fp-ts": "^2.11.3", + "io-ts": "^2.2.16", + "io-ts-types": "^0.5.16", + "rxjs": "^7.3.0" + } +} diff --git a/src/binance/apiTypes.ts b/src/binance/apiTypes.ts new file mode 100644 index 0000000..c30c50e --- /dev/null +++ b/src/binance/apiTypes.ts @@ -0,0 +1,56 @@ +import * as t from 'io-ts'; + +/* + [ + [ + 1499040000000, // Open time + "0.01634790", // Open + "0.80000000", // High + "0.01575800", // Low + "0.01577100", // Close + "148976.11427815", // Volume + 1499644799999, // Close time + "2434.19055334", // Quote asset volume + 308, // Number of trades + "1756.87402397", // Taker buy base asset volume + "28.46694368", // Taker buy quote asset volume + "17928899.62484339" // Ignore. + ] +] +*/ +// workaround: https://github.com/gcanti/io-ts/issues/431 +type TupleFn = ( + codecs: TCodecs, + name?: string +) => t.TupleType< + { + -readonly [K in keyof TCodecs]: TCodecs[K]; + }, + { + [K in keyof TCodecs]: TCodecs[K] extends t.Mixed + ? t.TypeOf + : unknown; + }, + { + [K in keyof TCodecs]: TCodecs[K] extends t.Mixed + ? t.OutputOf + : unknown; + } +>; +const tuple: TupleFn = t.tuple as any; +export const BinanceKlineIO = tuple([ + t.number, + t.string, + t.string, + t.string, + t.string, + t.string, + t.number, + t.string, + t.number, + t.string, + t.string, + t.string, +] as const); + +export type BinanceKline = t.TypeOf; diff --git a/src/binance/core.ts b/src/binance/core.ts new file mode 100644 index 0000000..2967ec6 --- /dev/null +++ b/src/binance/core.ts @@ -0,0 +1,298 @@ +import * as crypto from 'crypto'; +import axios from 'axios'; +import { flow, pipe } from 'fp-ts/lib/function'; +import { array, either, option } from 'fp-ts'; +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import ReconnectingWebSocket from 'reconnecting-websocket'; +import { Observable, Subject } from 'rxjs'; +import * as rxo from 'rxjs/operators'; +import { Json, parse } from 'fp-ts/lib/Json'; +import { + BinanceInterval, + BinanceSocketAggregatedTradeIO, + BinanceSocketBookTickerIO, + BinanceSocketDiffDepthIO, + BinanceSocketKlineIO, + BinanceSocketMiniTickerIO, + BinanceSocketPartialBookDepthIO, + BinanceSocketTickerIO, + BinanceSocketTradeIO, + BinanceSocketUserUpdateIO, +} from './socketTypes'; +import { Option } from 'fp-ts/lib/Option'; +import { observableEither } from 'fp-ts-rxjs'; +import queryStringLib from 'query-string'; + +// refer to binance-node-connector +/** + * NOTE: The array conversion logic is different from usual query string. + * E.g. symbols=["BTCUSDT","BNBBTC"] instead of symbols[]=BTCUSDT&symbols[]=BNBBTC + */ +const stringifyKeyValuePair = ([key, value]: [string, any]) => { + const valueString = Array.isArray(value) ? `["${value.join('","')}"]` : value; + return `${key}=${encodeURIComponent(valueString)}`; +}; + +export const buildQueryString = flow( + Object.entries, + array.filter(([_, value]) => (isOption(value) ? option.isSome(value) : true)), + array.map(([key, value]): [string, unknown] => + option.isSome(value) ? [key, value.value] : [key, value] + ), + array.map(stringifyKeyValuePair), + (kv) => kv.join('&') +); + +const isOption = (input: unknown): input is Option => + option.isNone(input as any) || option.isSome(input as any); + +// the whole query is stored in signature field in order to make it a single source of truth +// otherwise it is required to sign the query twice - once on the user side and then again in the client callback(`request` function) +export const makeSignQuery = + (apiSecret: string) => + >( + query: T + ): T & { signature: string; timestamp: t.Int } => { + const timestamp = Date.now(); + const queryString = buildQueryString({ + ...query, + timestamp, + }); + const signature = crypto + .createHmac('sha256', apiSecret) + .update(queryString) + .digest('hex'); + + return { + ...query, + timestamp: timestamp as t.Int, + signature: `${queryString}&signature=${signature}`, + }; + }; + +const getBinanceUrl = (url: string, rawQuery: string | undefined) => + rawQuery === undefined + ? url + : pipe( + rawQuery, + queryStringLib.parse, + (query) => + query['signature'] + ? (query['signature'] as string) + : buildQueryString(query), + (binanceQuery) => `${url}?${binanceQuery}` + ); + +export const fromPromiseToStream = ( + promise: () => Promise +): Observable> => + new Observable((subscriber) => { + promise() + .then((value) => { + if (!subscriber.closed) { + subscriber.next(either.right(value)); + subscriber.complete(); + } + }) + .catch((e) => subscriber.next(either.left(e))); + }); + +export type BinanceConfig = { + apiKey: string; + apiSecret: string; +}; + +// from devexperts swagger codegen +interface Request { + readonly method: + | 'GET' + | 'POST' + | 'PUT' + | 'DELETE' + | 'PATCH' + | 'HEAD' + | 'OPTIONS'; + readonly url: string; + readonly responseType: 'json' | 'blob' | 'text'; + readonly query?: string; + readonly body?: unknown; + readonly headers?: Record; +} + +export const makeBinanceHttpClient = ( + baseURL: string, + config: BinanceConfig +) => ({ + signQuery: makeSignQuery(config.apiSecret), + httpClient: { + ...observableEither.observableEither, + request: (request: Request) => { + const { method, query: rawQueryString, url: rawUrl } = request; + const url = getBinanceUrl(rawUrl, rawQueryString); + const instance = axios.create({ + baseURL, + headers: { + 'Content-Type': 'application/json', + 'X-MBX-APIKEY': config.apiKey, + }, + }); + instance.interceptors.response.use( + (r) => r, + (error) => Promise.reject(error.response.data) + ); + + return pipe( + () => + instance.request({ + method, + url, + }), + fromPromiseToStream, + rxo.map( + either.bimap( + (e) => new Error(String(e)), + (response) => response.data + ) + ) + ); + }, + }, +}); + +export const makeWebsocketStream = ( + url: string, + websocketImplementation?: any +): Observable> => { + const subject = new Subject>(); + const websocket = new ReconnectingWebSocket(url, undefined, { + debug: true, + minReconnectionDelay: 3000, + WebSocket: websocketImplementation, + }); + websocket.addEventListener('message', (e) => + subject.next( + pipe( + parse(e.data), + either.mapLeft((e) => new Error(String(e))) + ) + ) + ); + + return subject.asObservable(); +}; + +const fromWebsocketStream = ( + stream$: Observable>, + parser: (input: Json) => Either +) => + pipe( + stream$, + rxo.map( + either.chain( + flow( + parser, + either.mapLeft( + (e) => new Error(JSON.stringify(e.map((e) => e.context))) + ) + ) + ) + ) + ); + +// based on binance-connector +export const makeBinanceWebsocketClient = ( + baseURL: string, + websocketImplementation?: any +) => ({ + aggregatedTrade: (symbol: string) => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/${symbol.toLowerCase()}@aggTrade`, + websocketImplementation + ), + BinanceSocketAggregatedTradeIO.decode + ), + trade: (symbol: string) => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/${symbol.toLowerCase()}@trade`, + websocketImplementation + ), + BinanceSocketTradeIO.decode + ), + kline: (symbol: string, interval: BinanceInterval) => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/${symbol.toLowerCase()}@kline_${interval}`, + websocketImplementation + ), + BinanceSocketKlineIO.decode + ), + miniTicker: (symbol: string) => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/${symbol.toLowerCase()}@miniTicker`, + websocketImplementation + ), + BinanceSocketMiniTickerIO.decode + ), + miniTickers: () => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/!miniTicker@arr`, + websocketImplementation + ), + t.array(BinanceSocketMiniTickerIO).decode + ), + ticker: (symbol: string) => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/${symbol.toLowerCase()}@ticker`, + websocketImplementation + ), + BinanceSocketTickerIO.decode + ), + tickers: () => + fromWebsocketStream( + makeWebsocketStream(`${baseURL}/ws/!ticker@arr`, websocketImplementation), + t.array(BinanceSocketTickerIO).decode + ), + bookTicker: (symbol: string) => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/${symbol.toLowerCase()}@bookTicker`, + websocketImplementation + ), + BinanceSocketBookTickerIO.decode + ), + bookTickers: () => + fromWebsocketStream( + makeWebsocketStream(`${baseURL}/ws/!bookTicker`, websocketImplementation), + BinanceSocketBookTickerIO.decode + ), + partialBookDepth: (symbol: string, levels: 5 | 10 | 20, speed: 100 | 1000) => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/${symbol.toLowerCase()}@depth${levels}@${speed}`, + websocketImplementation + ), + BinanceSocketPartialBookDepthIO.decode + ), + diffBookDepth: (symbol: string, speed: 100 | 1000) => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/${symbol.toLowerCase()}@depth@${speed}`, + websocketImplementation + ), + BinanceSocketDiffDepthIO.decode + ), + userData: (listenKey: string) => + fromWebsocketStream( + makeWebsocketStream( + `${baseURL}/ws/${listenKey}`, + websocketImplementation + ), + BinanceSocketUserUpdateIO.decode + ), +}); diff --git a/src/binance/socketTypes.ts b/src/binance/socketTypes.ts new file mode 100644 index 0000000..d9cdc35 --- /dev/null +++ b/src/binance/socketTypes.ts @@ -0,0 +1,356 @@ +import * as t from 'io-ts'; + +export const BinanceSocketOrderTypeIO = t.union([ + t.literal('LIMIT'), + t.literal('MARKET'), + t.literal('STOP_LOSS'), + t.literal('STOP_LOSS_LIMIT'), + t.literal('TAKE_PROFIT'), + t.literal('TAKE_PROFIT_LIMIT'), + t.literal('LIMIT_MAKER'), +]); + +export type BinanceSocketOrderType = t.TypeOf; + +export const BinanceSocketSideIO = t.union([ + t.literal('SELL'), + t.literal('BUY'), +]); + +export type BinanceSocketSide = t.TypeOf; + +export const BinanceTimeInForceIO = t.union([ + t.literal('GTC'), + t.literal('IOC'), + t.literal('FOK'), +]); + +export type BinanceTimeInForce = t.TypeOf; + +export const BinanceIntervalIO = t.union([ + t.literal('1m'), + t.literal('3m'), + t.literal('5m'), + t.literal('15m'), + t.literal('30m'), + t.literal('1h'), + t.literal('2h'), + t.literal('4h'), + t.literal('6h'), + t.literal('8h'), + t.literal('12h'), + t.literal('1d'), + t.literal('3d'), + t.literal('1w'), + t.literal('1M'), +]); + +export type BinanceInterval = t.TypeOf; + +export const BinanceOrderResponseIO = t.type({ + symbol: t.string, + orderId: t.number, + clientOrderId: t.string, + transactTime: t.number, + price: t.string, + origQty: t.string, + executedQty: t.string, + status: t.string, + timeInForce: t.string, + type: t.string, + side: t.string, +}); + +export type BinanceOrderResponse = t.TypeOf; + +// websocket +export const BinanceSocketAggregatedTradeIO = t.type({ + e: t.literal('aggTrade'), // Event type + E: t.Int, // Event time + s: t.string, // Symbol + a: t.Int, // Aggregate trade ID + p: t.string, // Price + q: t.string, // Quantity + f: t.Int, // First trade ID + l: t.Int, // Last trade ID + T: t.Int, // Trade time + m: t.boolean, // Is the buyer the market maker? + M: t.boolean, // Ignore +}); + +export type BinanceSocketAggregatedTrade = t.TypeOf< + typeof BinanceSocketAggregatedTradeIO +>; + +export const BinanceSocketTradeIO = t.type({ + e: t.literal('trade'), + E: t.Int, // Event time + s: t.string, // Symbol + t: t.Int, // Trade ID + p: t.string, // Price + q: t.string, // Quantity + b: t.Int, // Buyer order ID + a: t.Int, // Seller order ID + T: t.Int, // Trade time + m: t.boolean, // Is the buyer the market maker? + M: t.boolean, // Ignore +}); + +export type BinanceSocketTrade = t.TypeOf; + +export const BinanceSocketKlineIO = t.type({ + e: t.literal('kline'), // Event type + E: t.number, // Event time + s: t.string, // Symbol + k: t.type({ + t: t.number, // Kline start time + T: t.number, // Kline close time + s: t.string, // Symbol + i: BinanceIntervalIO, // Interval + f: t.number, // First trade ID + L: t.number, // Last trade ID + o: t.string, // Open price + c: t.string, // Close price + h: t.string, // High price + l: t.string, // Low price + v: t.string, // Base asset volume + n: t.number, // Number of trades + x: t.boolean, // Is this kline closed? + q: t.string, // Quote asset volume + V: t.string, // Taker buy base asset volume + Q: t.string, // Taker buy quote asset volume + B: t.string, // Ignore + }), +}); + +export type BinanceSocketKline = t.TypeOf; + +export const BinanceSocketMiniTickerIO = t.type({ + e: t.literal('24hrMiniTicker'), // Event type + E: t.Int, // Event time + s: t.string, // Symbol + c: t.string, // Close price + o: t.string, // Open price + h: t.string, // High price + l: t.string, // Low price + v: t.string, // Total traded base asset volume + q: t.string, // Total traded quote asset volume +}); + +export type BinanceSocketMiniTicker = t.TypeOf< + typeof BinanceSocketMiniTickerIO +>; + +export const BinanceSocketTickerIO = t.type({ + e: t.literal('24hrTicker'), // Event type + E: t.Int, // Event time + s: t.string, // Symbol + p: t.string, // Price change + P: t.string, // Price change percent + w: t.string, // Weighted average price + x: t.string, // First trade(F)-1 price (first trade before the 24hr rolling window) + c: t.string, // Last price + Q: t.string, // Last quantity + b: t.string, // Best bid price + B: t.string, // Best bid quantity + a: t.string, // Best ask price + A: t.string, // Best ask quantity + o: t.string, // Open price + h: t.string, // High price + l: t.string, // Low price + v: t.string, // Total traded base asset volume + q: t.string, // Total traded quote asset volume + O: t.Int, // Statistics open time + C: t.Int, // Statistics close time + F: t.Int, // First trade ID + L: t.Int, // Last trade Id + n: t.Int, // Total number of trades +}); + +export type BinanceSocketTicker = t.TypeOf; + +export const BinanceSocketBookTickerIO = t.type({ + u: t.Int, // order book updateId + s: t.string, // symbol + b: t.string, // best bid price + B: t.string, // best bid qty + a: t.string, // best ask price + A: t.string, // best ask qty +}); + +export type BinanceSocketBookTicker = t.TypeOf< + typeof BinanceSocketBookTickerIO +>; + +export const BinanceSocketPartialBookDepthIO = t.type({ + lastUpdateId: t.Int, // Last update ID + bids: t.array(t.tuple([t.string, t.string])), // [Price level to be updated, Quantity][] + asks: t.array(t.tuple([t.string, t.string])), // [Price level to be updated, Quantity][] +}); + +export type BinanceSocketPartialBookDepth = t.TypeOf< + typeof BinanceSocketPartialBookDepthIO +>; + +export const BinanceSocketDiffDepthIO = t.type({ + e: t.literal('depthUpdate'), // Event type + E: t.Int, // Event time + s: t.string, // Symbol + U: t.Int, // First update ID in event + u: t.Int, // Final update ID in event + b: t.array(t.tuple([t.string, t.string])), // [Price level to be updated, Quantity][] + a: t.array(t.tuple([t.string, t.string])), // [Price level to be updated, Quantity][] +}); + +export type BinanceSocketDiffDepth = t.TypeOf; + +export const BinanceSocketAccountUpdateIO = t.type({ + e: t.literal('outboundAccountPosition'), //Event type + E: t.Int, //Event Time + u: t.Int, //Time of last account update + B: + //Balances Array + t.array( + t.type({ + a: t.string, //Asset + f: t.string, //Free + l: t.string, //Locked + }) + ), +}); + +export type BinanceSocketAccountUpdate = t.TypeOf< + typeof BinanceSocketAccountUpdateIO +>; + +export const BinanceSocketBalanceUpdateIO = t.type({ + e: t.literal('balanceUpdate'), //Event Type + E: t.Int, //Event Time + a: t.string, //Asset + d: t.string, //Balance Delta + T: t.Int, //Clear Time +}); + +export type BinanceSocketBalanceUpdate = t.TypeOf< + typeof BinanceSocketBalanceUpdateIO +>; + +export const BinanceSocketExecutionTypeIO = t.union([ + t.literal('NEW'), + t.literal('CANCELED'), + t.literal('REPLACED'), + t.literal('TRADE'), + t.literal('EXPIRED'), +]); + +export type BinanceSocketExecutionType = t.TypeOf< + typeof BinanceSocketExecutionTypeIO +>; + +export const BinanceSocketOrderStatusIO = t.union([ + t.literal('NEW'), + t.literal('PARTIALLY_FILLED'), + t.literal('FILLED'), + t.literal('CANCELLED'), + t.literal('PENDING_CANCEL'), + t.literal('REJECTED'), + t.literal('EXPIRED'), +]); + +export type BinanceSocketOrderStatus = t.TypeOf< + typeof BinanceSocketOrderStatusIO +>; + +export const BinanceSocketOrderUpdateIO = t.type({ + e: t.literal('executionReport'), // Event type + E: t.Int, // Event time + s: t.string, // Symbol + c: t.string, // Client order ID + S: BinanceSocketSideIO, // Side + o: BinanceSocketOrderTypeIO, // Order type + f: BinanceTimeInForceIO, // Time in force + q: t.string, // Order quantity + p: t.string, // Order price + P: t.string, // Stop price + F: t.string, // Iceberg quantity + g: t.Int, // OrderListId + C: t.string, // Original client order ID; This is the ID of the order being canceled + x: BinanceSocketExecutionTypeIO, // Current execution type + X: BinanceSocketOrderStatusIO, // Current order status + r: t.string, // Order reject reason; will be an error code. ('NONE' or error code) + i: t.Int, // Order ID + l: t.string, // Last executed quantity + z: t.string, // Cumulative filled quantity + L: t.string, // Last executed price + n: t.string, // Commission amount + N: t.null, // Commission asset + T: t.Int, // Transaction time + t: t.Int, // Trade ID + I: t.Int, // Ignore + w: t.boolean, // Is the order on the book? + m: t.boolean, // Is this trade the maker side? + M: t.boolean, // Ignore + O: t.Int, // Order creation time + Z: t.string, // Cumulative quote asset transacted quantity + Y: t.string, // Last quote asset transacted quantity (i.e. lastPrice * lastQty) + Q: t.string, // Quote Order Qty +}); + +export type BinanceSocketOrderUpdate = t.TypeOf< + typeof BinanceSocketOrderUpdateIO +>; + +export const BinanceSocketOCOListStatusIO = t.union([ + t.literal('RESPONSE'), + t.literal('EXEC_STARTED'), + t.literal('ALL_DONE'), +]); + +export type BinanceSocketOCOListStatus = t.TypeOf< + typeof BinanceSocketOCOListStatusIO +>; + +export const BinanceSocketOCOListOrderStatusIO = t.union([ + t.literal('EXECUTING'), + t.literal('ALL_DONE'), + t.literal('REJECT'), +]); + +export type BinanceSocketOCOListOrderStatus = t.TypeOf< + typeof BinanceSocketOCOListOrderStatusIO +>; + +export const BinanceSocketListStatusIO = t.type({ + e: t.literal('listStatus'), //Event Type + E: t.Int, //Event Time + s: t.string, //Symbol + g: t.Int, //OrderListId + c: t.literal('OCO'), //Contingency Type + l: BinanceSocketOCOListStatusIO, //List Status Type + L: BinanceSocketOCOListOrderStatusIO, //List Order Status + r: t.string, //List Reject Reason ('NONE' or error code) + C: t.string, //List Client Order ID + T: t.Int, //Transaction Time + O: t.array( + t.type({ + s: t.string, //Symbol + i: t.Int, // orderId + c: t.string, //ClientOrderId + }) + ), +}); + +export type BinanceSocketListStatus = t.TypeOf< + typeof BinanceSocketListStatusIO +>; + +export const BinanceSocketUserUpdateIO = t.union([ + BinanceSocketAccountUpdateIO, + BinanceSocketBalanceUpdateIO, + BinanceSocketOrderUpdateIO, + BinanceSocketListStatusIO, +]); + +export type BinanceSocketUserUpdate = t.TypeOf< + typeof BinanceSocketUserUpdateIO +>; diff --git a/src/generate.ts b/src/generate.ts new file mode 100644 index 0000000..641e35c --- /dev/null +++ b/src/generate.ts @@ -0,0 +1,80 @@ +import { generate } from '@devexperts/swagger-codegen-ts'; +import * as path from 'path'; +import { serialize as serializeOpenAPI3 } from '@devexperts/swagger-codegen-ts/dist/language/typescript/3.0'; +import { OpenapiObjectCodec } from '@devexperts/swagger-codegen-ts/dist/schema/3.0/openapi-object'; +import { taskEither } from 'fp-ts'; +import { replaceInFile } from 'replace-in-file'; +import { identity, pipe } from 'fp-ts/lib/function'; +import axios from 'axios'; +import fs from 'fs'; +import { promisify } from 'util'; + +// api has a parameter called 'symbol', which conflicts with js' native type +const fixSymbolType = (glob: string) => + replaceInFile({ + files: glob, + from: [ + 'export type symbol = string;', + 'export const symbolIO = string;', + new RegExp( + `import { symbol, symbolIO } from '../components/parameters/symbol';`, + 'g' + ), + new RegExp('symbol: symbol', 'g'), + new RegExp('symbolIO.', 'g'), + ], + to: [ + 'export type tickerSymbol = string;', + 'export const tickerSymbolIO = string;', + "import { tickerSymbol, tickerSymbolIO } from '../components/parameters/symbol';", + 'symbol: tickerSymbol', + 'tickerSymbolIO.', + ], + }); + +export const generateApifromFile = ( + baseDir: string, + specPath: string, + out: string +) => + pipe( + generate({ + cwd: baseDir, + spec: path.resolve(baseDir, specPath), + out: path.resolve(baseDir, out), + language: serializeOpenAPI3, + decoder: OpenapiObjectCodec, + }), + taskEither.chain(() => + taskEither.tryCatch( + () => + fixSymbolType(`${path.resolve(baseDir, out)}/spot_api.yaml/**/*.ts`), + identity + ) + ) + ); + +export const generateApifromURL = ( + baseDir: string, + specUrl: string, + out: string +) => + pipe( + taskEither.tryCatch(() => axios.get(specUrl), identity), + taskEither.chain((response) => + taskEither.tryCatch( + () => promisify(fs.writeFile)('spot_api.yaml', response.data), + identity + ) + ), + taskEither.chain(() => generateApifromFile(baseDir, 'spot_api.yaml', out)), + taskEither.chain(() => + taskEither.tryCatch( + () => promisify(fs.unlink)('spot_api.yaml'), + (e) => { + console.log('Failed to cleanup'); + return e; + } + ) + ) + ); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..af1ace4 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,4 @@ +export * from './binance/core'; +export * from './binance/socketTypes'; +export * from './binance/apiTypes'; +export * from './generate'; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..27a582d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "strict": true, + "module": "commonjs", + "target": "es6", + "sourceMap": false, + "jsx": "react", + "moduleResolution": "node", + "noUnusedLocals": false, + "noUnusedParameters": false, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "declaration": true, + "outDir": "dist", + }, + "include": [ + "src/**/*", + "*.ts" + ], + "exclude": [ + "./node_modules" + ] +} \ No newline at end of file