{"id":26582969,"url":"https://github.com/capybara003/cex-platform","last_synced_at":"2025-06-13T22:33:31.600Z","repository":{"id":281890924,"uuid":"946447487","full_name":"Capybara003/CEX-platform","owner":"Capybara003","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-11T07:13:21.000Z","size":658,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-11T17:54:07.890Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Capybara003.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-11T06:41:25.000Z","updated_at":"2025-03-11T17:49:46.000Z","dependencies_parsed_at":"2025-03-11T17:54:14.496Z","dependency_job_id":"1e035cea-e861-402a-9997-c554e3d1e995","html_url":"https://github.com/Capybara003/CEX-platform","commit_stats":null,"previous_names":["capybara003/cex-platform"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Capybara003%2FCEX-platform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Capybara003%2FCEX-platform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Capybara003%2FCEX-platform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Capybara003%2FCEX-platform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Capybara003","download_url":"https://codeload.github.com/Capybara003/CEX-platform/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245072955,"owners_count":20556461,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-23T08:19:12.777Z","updated_at":"2025-03-23T08:19:13.253Z","avatar_url":"https://github.com/Capybara003.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# safe-cex\n\n[![npm version](https://badge.fury.io/js/safe-cex.svg)](https://badge.fury.io/js/safe-cex)\n![npm](https://img.shields.io/npm/dt/safe-cex)\n![Discord](https://img.shields.io/discord/965643018004738189)\n\n![image](https://user-images.githubusercontent.com/893837/228979174-32b7f08d-6e13-4bdd-9598-e25846911335.png)\n\n\u003e An OpenSource TypeScript library to create rich trading cryptocurrencies interfaces\n\n## Introduction\n\nIt is an Open-source TypeScript library that provides an easy-to-use interface for communicating with exchanges. It is designed to be used by trading platforms like tuleep.trade, allowing them to interact with exchanges like Bybit and Binance Futures to execute trades on behalf of their users.\n\nThe library includes a set of API methods that abstract away the complexities of the exchanges' REST and WebSocket APIs, providing a simple and consistent interface for managing orders, positions, balances, and more.\n\nIt also implements robust error handling, rate limiting, and other safeguards to prevent common trading pitfalls and ensure the safety of user funds.\n\nOne key feature of safe-cex is its support for multiple exchanges, which allows tuleep.trade to offer a wider range of trading options to its users.\n\nCurrently, the library supports Bybit and Binance Futures contracts, OKX Perpetual Swaps and WOO X Futures.\n\n## Differences with CCXT\n\n- safe-cex handles for you the lifecycle of fetching, and updating data from exchanges\n- safe-cex exposes simple methods to place any type of orders\n- safe-cex handles for you orders size limits and precisions of orders\n- safe-cex expose the same interface for every exchanges\n- safe-cex is oriented for in-browser usage\n\n## Exchanges supported\n\n- [Bybit](https://partner.bybit.com/b/safecex) Futures USDT contracts \u0026 futures unified Margin\n- [Binance](https://accounts.binance.com/en/register?ref=KOLLSXK0) USD-M futures (USDT contracts)\n- [Bitget](https://bonus.bitget.com/tuleep) USDT-M Futures (USDT contracts)\n- [WOO X](https://x.woo.org/en/trade?ref=safecex) Futures USDT \u0026 futures unified margin\n- [OKX](https://www.okx.com/join/TULEEP) Perpetuals unified margin\n- [GateIO](https://www.gate.io/signup/13385879) Futures USDT contracts\n- [Blofin](https://partner.blofin.com/d/tuleeptrade) Futures USDT contracts\n- [Phemex](https://phemex.com/a/k/tuleep) Futures USDT contracts\n\n---\n\n## Installation\n\n- `npm install --save safe-cex`\n\n## Getting started\n\nTo initialize the exchange library, you will need:\n\n- API key / secret\n- A CORS-Anywhere server if you are using Binance testnet (they do not support CORS)\n\n```ts\nimport { createExchange } from \"safe-cex\";\n\n// Initialize exchange class object\nconst exchange = createExchange(\n  \"bybit\" | \"binance\" | \"okx\" | \"woo\" | \"gate\" | \"bitget\" | \"blofin\" | \"phemex\",\n  {\n    key: API_KEY,\n    secret: API_SECRET,\n    applicationId: string, // FOR WOO X\n    passphrase: string, // FOR OKX, BITGET \u0026 BLOFIN\n    testnet: boolean,\n    corsAnywhere: \"https://cors-anywhere.example.com\",\n    extra?:{\n      // polling rate of balance and positions, defaults to API request rate limit\n      // usefull if you are running a TWAP bot and you don't care about having positions \u0026 balance up to the ms updates\n      // ex: 5000 (poll every 5s)\n      tickInterval?: number;\n      // override exchange endpoints\n      // for instance you have a proxy with a whitelisted IP\n      // or you have access to a \"VIP\" endpoint with increased limits\n      [exchange]: {\n        http: {\n          livenet: 'xxxx',\n          testnet: 'xxxx'\n        },\n        ws: {\n          public: {\n            livenet: 'xxxx',\n            testnet: 'xxxx',\n          },\n          private: {\n            livenet: 'xxxx',\n            testnet: 'xxxx'\n          }\n        }\n      }\n    }\n  }\n);\n\n// Start the exchange syncronization\n// - will fetch markets, tickers, orders, positions, balance...\nawait exchange.start();\n```\n\n## Exchange store\n\nsafe-cex maintains a inner-store with all the up-to-date exchanges informations:\n\n```ts\ntype Store = {\n  latency: number;\n  balance: Balance;\n  markets: Market[];\n  tickers: Ticker[];\n  orders: Order[];\n  positions: Position[];\n  loaded: {\n    balance: boolean;\n    orders: boolean;\n    markets: boolean;\n    tickers: boolean;\n    positions: boolean;\n  };\n};\n```\n\n## Events\n\nsafe-cex creates an exchange is an event-emitter object, you can subscribe to events and react accordingly.\n\n### `update`\n\nThis event is called everytime the inner-store of safe-cex is updated.\n\n```ts\nlet storeCopy = {};\n\nexchange.on(\"update\", (store: Store) =\u003e {\n  console.log(\"exchange store update\");\n  storeCopy = store;\n});\n```\n\n### `fill`\n\nThis event is called when an order is filled, this allows you to display a notification when this happens.\n\n```ts\ntype FillEvent = {\n  amount: number;\n  price: number;\n  side: \"buy\" | \"sell\";\n  symbol: string;\n};\n\nexchange.on(\"fill\", (event: FillEvent) =\u003e {\n  console.log(\n    `${event.side} ${event.amount} ${event.symbol} at ${event.price}`\n  );\n});\n```\n\n### `error`\n\nThis event is called when an error has occured or the exchange API responded with an error status.\n\n```ts\nexchange.on(\"error\", (error: string) =\u003e {\n  window.alert(error);\n});\n```\n\n### `log`\n\nThis event is called when a new log message is emitted, you can display those debuging purposes.\n\n```ts\nenum LogSeverity {\n  Warning = \"warning\",\n  Error = \"error\",\n  Info = \"info\",\n}\n\nexchange.on(\"log\", (message: string, severity: LogSeverity) =\u003e {\n  console.log(`[${severity}] ${message}`);\n});\n```\n\n## Public methods\n\n### `validateAccount()`\n\n- Can be called before `exchange.start()` to ensure API keys are valid and have the right permissions\n- Returns an empty string if valid, otherwise returns a string with error\n\n### `start()`\n\n- Method to be called before trying to place orders\n- It starts the lifecycle of safe-cex and fetch all the needed data\n- You can use `store.loaded` object to know when it's ready\n\n### `fetchOHLCV()`\n\n```ts\ntype Timeframe =\n  | \"1m\"\n  | \"3m\"\n  | \"5m\"\n  | \"15m\"\n  | \"30m\"\n  | \"1h\"\n  | \"2h\"\n  | \"4h\"\n  | \"6h\"\n  | \"12h\"\n  | \"1d\"\n  | \"1w\";\n\ntype OHLCVOptions = {\n  symbol: string;\n  interval: Timeframe;\n};\n\ntype Candle = {\n  timestamp: number;\n  open: number;\n  high: number;\n  low: number;\n  close: number;\n  volume: number;\n};\n\nconst candles: Candle[] = await exchange.fetchOHLCV({\n  // market symbol, can be found in exchange.store.markets[index].symbol\n  symbol: \"BTCUSDT\",\n  timeframe: \"15m\",\n});\n```\n\n### `listenOHLCV()`\n\n- Subscribe to exchange kline websocket\n- Takes a `callback()` function to be called when candle has been updated\n- Returns a `dispose()` function to un-subscribe websocket topic\n\n```ts\nconst callback = (candle: Candle) =\u003e {\n  console.log(`Candle updated, current price: ${candle.close}`);\n};\n\nconst dispose = exchange.listenOHLCV(\n  { symbol: \"BTCUSDT\", timeframe: \"15m\" },\n  callback\n);\n\n// when finished listening\ndispose();\n```\n\n### `listenOrderBook()`\n\n- Subscribe to exchange symbol orderbook\n- Takes a `callback()` function to be called when order book has been updated\n- Returns a `dispose()` function to un-subscribe weboscket topic\n\n```ts\ntype OrderBookOrders = {\n  price: number;\n  amount: number;\n  total: number;\n};\n\ntype OrderBook = {\n  bids: OrderBookOrders[];\n  asks: OrderBookOrders[];\n};\n\nconst callback = (orderBook: OrderBook) =\u003e {\n  console.log(JSON.stringify(orderBook, null, 4));\n};\n\nconst dispose = exchange.listenOrderBook(\"BTCUSDT\", callback);\n\n// when finished\ndispose();\n```\n\n### `placeOrder()`\n\n- Method to create an order on exchange\n- Can set stopLoss / takeProfit at the same time\n- Returns an Array of orderIds\n\n```ts\nenum OrderType {\n  Market = \"market\",\n  Limit = \"limit\",\n  StopLoss = \"stop_market\",\n  TakeProfit = \"take_profit_market\",\n  TralingStopLoss = \"trailing_stop_market\",\n}\n\nenum OrderSide {\n  Buy = \"buy\",\n  Sell = \"sell\",\n}\n\nenum OrderTimeInForce {\n  GoodTillCancel = \"GoodTillCancel\",\n  ImmediateOrCancel = \"ImmediateOrCancel\",\n  FillOrKill = \"FillOrKill\",\n  PostOnly = \"PostOnly\",\n}\n\ntype PlaceOrderOpts = {\n  symbol: string;\n  type: OrderType;\n  side: OrderSide;\n  amount: number;\n  price?: number;\n  stopLoss?: number;\n  takeProfit?: number;\n  reduceOnly?: boolean;\n  timeInForce?: OrderTimeInForce;\n};\n\n// Place a market order of 0.25 BTC\nawait exchange.placeOrder({\n  symbol: \"BTCUSDT\",\n  type: OrderType.Market,\n  side: OrderSide.Buy,\n  amount: 0.25,\n});\n\n// Place a limit order of 1 ETH at 1700$\n// and set stopLoss at 1650\n// and set takeProfit at 1750\nconst orderIds: string[] = await exchange.placeOrder({\n  symbol: \"ETHUSDT\",\n  type: OrderType.Limit,\n  side: OrderSide.Buy,\n  amount: 1,\n  price: 1700,\n  stopLoss: 1650,\n  takeProfit: 1750,\n  timeInForce: OrderTimeInForce.GoodTillCancel,\n});\n```\n\n### `placeOrders()`\n\n- Same method as `placeOrder()` but for multiple orders\n- Pease use this method when possible, it will batch orders creations on exchanges API\n- There's no limit of orders to be passed\n- Returns an Array of orderIds\n\n### `updateOrder()`\n\n- Method to be called for updating an order price or amount\n- This supports updating price of take profit and stop loss orders\n- Returns an Array of orderIds\n\n```ts\n//  we take the first existing order as example\nconst originalOrder = exchange.store.orders[0];\n\n// update price of order\nconst updatedOrderIds: string[] = await exchange.updateOrder({\n  order: originalOrder,\n  update: { price: 1700 },\n});\n\n// update amount of order\nconst updatedOrderIds: string[] = await exchange.updateOrder({\n  order: originalOrder,\n  update: { amount: 2 },\n});\n```\n\n### `cancelOrders()`\n\n- Method for cancelling multiple orders at the same time\n\n```ts\nconst orders = [exchange.store.orders[0], exchange.store.orders[1]];\nawait exchange.cancelOrders(orders);\n```\n\n### `cancelSymbolOrders()`\n\n- Method for cancelling all orders relative to a symbol\n\n```ts\nawait exchange.cancelSymbolOrders(\"BTCUSDT\");\n```\n\n### `cancelAllOrders()`\n\n- Method for cancelling all existing orders\n\n```ts\nawait exchange.cancelAllOrders();\n```\n\n### `setLeverage()`\n\n- Method used to update the leverage on a symbol\n- It will check for min/max leverage of market and will stay in those boundaries\n  - eg: you set leverage x50 but market accepts max x25, it will be set to x25\n\n```ts\nawait exchange.setLeverage(\"BTCUSDT\", 125);\n```\n\n### `setAllLeverage()`\n\n- Method used to update all the leverage setting for all markets\n- It will check for min/max leverage of market and will stay in those boundaries\n\n```ts\nawait exchange.setAllLeverage(100);\n```\n\n### `changePositionMode()`\n\n- Method to be used to switch between Hedge/One-way mode\n- It acts on every contracts\n- You must have no positions open to user\n\n```ts\n// switch hedge-mode\nawait exchange.changePositionMode(true);\n// switch one-way\nawait exchange.changePositionMode(false);\n```\n\n### `nuke()`\n\n- Closes all positions at market price\n- Cancel all existing orders\n\n```ts\nawait exchange.nuke();\n```\n\n### `dispose()`\n\n- Method to be called when you don't need the exchange instance anymore\n- It has to be called for cleaning all subscribtions, data streams with exchange, etc...\n\n```ts\nawait exchange.dispose();\n```\n\n---\n\n## Known issues\n\n### Using with next.js\n\nBecause of `nanoid` package, in next.config.js add:\n\n```ts\ntranspilePackages: ['safe-cex'],\nexperimental: {\n  esmExternals: 'loose',\n}\n```\n\n## Donations\n\nIf you found this project interesting or useful, create accounts with my referral links:\n\n- [Bybit](https://partner.bybit.com/b/safecex) **Up to $30,000 deposit bonus**\n- [Blofin](https://partner.blofin.com/d/tuleeptrade) **$5,000 welcome bonus \u0026 no KYC required**\n- [OKX](https://www.okx.com/join/TULEEP) **20% less fees, up to $10,000 deposit bonus**\n- [Bitget](https://bonus.bitget.com/tuleep) **10% less fees, up to $1,000 deposit bonus**\n- [WOO X](https://x.woo.org/en/trade?ref=safecex) **Deposit $100 and 0 fees for 14 days!**\n- [Binance](https://accounts.binance.com/en/register?ref=KOLLSXK0)\n- [GateIO](https://www.gate.io/signup/13385879)\n- [Phemex](https://phemex.com/a/k/tuleep)\n\nOr buy me a coffee with a crypto donation:\n\n- ETH/BSC/MATIC/AVAX: `0xFF2da578C73bC694fd767A1CC77160002C2003E6`\n\n## Contributions \u0026 Pull Requests\n\nFeel free to create issues, PRs and start a discussion ❤️\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapybara003%2Fcex-platform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcapybara003%2Fcex-platform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapybara003%2Fcex-platform/lists"}