
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
[](https://badge.fury.io/js/safe-cex)  

An OpenSource TypeScript library to create rich trading cryptocurrencies interfaces
It 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.
The 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.
It also implements robust error handling, rate limiting, and other safeguards to prevent common trading pitfalls and ensure the safety of user funds.
One 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.
Currently, the library supports Bybit and Binance Futures contracts, OKX Perpetual Swaps and WOO X Futures.
npm install --save safe-cexTo initialize the exchange library, you will need:
import { createExchange } from "safe-cex";
// Initialize exchange class object
const exchange = createExchange(
"bybit" | "binance" | "okx" | "woo" | "gate" | "bitget" | "blofin" | "phemex",
{
key: API_KEY,
secret: API_SECRET,
applicationId: string, // FOR WOO X
passphrase: string, // FOR OKX, BITGET & BLOFIN
testnet: boolean,
corsAnywhere: "https://cors-anywhere.example.com",
extra?:{
// polling rate of balance and positions, defaults to API request rate limit
// usefull if you are running a TWAP bot and you don't care about having positions & balance up to the ms updates
// ex: 5000 (poll every 5s)
tickInterval?: number;
// override exchange endpoints
// for instance you have a proxy with a whitelisted IP
// or you have access to a "VIP" endpoint with increased limits
[exchange]: {
http: {
livenet: 'xxxx',
testnet: 'xxxx'
},
ws: {
public: {
livenet: 'xxxx',
testnet: 'xxxx',
},
private: {
livenet: 'xxxx',
testnet: 'xxxx'
}
}
}
}
}
);
// Start the exchange syncronization
// - will fetch markets, tickers, orders, positions, balance...
await exchange.start();
safe-cex maintains a inner-store with all the up-to-date exchanges informations:
type Store = {
latency: number;
balance: Balance;
markets: Market[];
tickers: Ticker[];
orders: Order[];
positions: Position[];
loaded: {
balance: boolean;
orders: boolean;
markets: boolean;
tickers: boolean;
positions: boolean;
};
};
safe-cex creates an exchange is an event-emitter object, you can subscribe to events and react accordingly.
updateThis event is called everytime the inner-store of safe-cex is updated.
let storeCopy = {};
exchange.on("update", (store: Store) => {
console.log("exchange store update");
storeCopy = store;
});
fillThis event is called when an order is filled, this allows you to display a notification when this happens.
type FillEvent = {
amount: number;
price: number;
side: "buy" | "sell";
symbol: string;
};
exchange.on("fill", (event: FillEvent) => {
console.log(
`${event.side} ${event.amount} ${event.symbol} at ${event.price}`
);
});
errorThis event is called when an error has occured or the exchange API responded with an error status.
exchange.on("error", (error: string) => {
window.alert(error);
});
logThis event is called when a new log message is emitted, you can display those debuging purposes.
enum LogSeverity {
Warning = "warning",
Error = "error",
Info = "info",
}
exchange.on("log", (message: string, severity: LogSeverity) => {
console.log(`[${severity}] ${message}`);
});
validateAccount()exchange.start() to ensure API keys are valid and have the right permissionsstart()store.loaded object to know when it's readyfetchOHLCV()type Timeframe =
| "1m"
| "3m"
| "5m"
| "15m"
| "30m"
| "1h"
| "2h"
| "4h"
| "6h"
| "12h"
| "1d"
| "1w";
type OHLCVOptions = {
symbol: string;
interval: Timeframe;
};
type Candle = {
timestamp: number;
open: number;
high: number;
low: number;
close: number;
volume: number;
};
const candles: Candle[] = await exchange.fetchOHLCV({
// market symbol, can be found in exchange.store.markets[index].symbol
symbol: "BTCUSDT",
timeframe: "15m",
});
listenOHLCV()callback() function to be called when candle has been updateddispose() function to un-subscribe websocket topicconst callback = (candle: Candle) => {
console.log(`Candle updated, current price: ${candle.close}`);
};
const dispose = exchange.listenOHLCV(
{ symbol: "BTCUSDT", timeframe: "15m" },
callback
);
// when finished listening
dispose();
listenOrderBook()callback() function to be called when order book has been updateddispose() function to un-subscribe weboscket topictype OrderBookOrders = {
price: number;
amount: number;
total: number;
};
type OrderBook = {
bids: OrderBookOrders[];
asks: OrderBookOrders[];
};
const callback = (orderBook: OrderBook) => {
console.log(JSON.stringify(orderBook, null, 4));
};
const dispose = exchange.listenOrderBook("BTCUSDT", callback);
// when finished
dispose();
placeOrder()enum OrderType {
Market = "market",
Limit = "limit",
StopLoss = "stop_market",
TakeProfit = "take_profit_market",
TralingStopLoss = "trailing_stop_market",
}
enum OrderSide {
Buy = "buy",
Sell = "sell",
}
enum OrderTimeInForce {
GoodTillCancel = "GoodTillCancel",
ImmediateOrCancel = "ImmediateOrCancel",
FillOrKill = "FillOrKill",
PostOnly = "PostOnly",
}
type PlaceOrderOpts = {
symbol: string;
type: OrderType;
side: OrderSide;
amount: number;
price?: number;
stopLoss?: number;
takeProfit?: number;
reduceOnly?: boolean;
timeInForce?: OrderTimeInForce;
};
// Place a market order of 0.25 BTC
await exchange.placeOrder({
symbol: "BTCUSDT",
type: OrderType.Market,
side: OrderSide.Buy,
amount: 0.25,
});
// Place a limit order of 1 ETH at 1700$
// and set stopLoss at 1650
// and set takeProfit at 1750
const orderIds: string[] = await exchange.placeOrder({
symbol: "ETHUSDT",
type: OrderType.Limit,
side: OrderSide.Buy,
amount: 1,
price: 1700,
stopLoss: 1650,
takeProfit: 1750,
timeInForce: OrderTimeInForce.GoodTillCancel,
});
placeOrders()placeOrder() but for multiple ordersupdateOrder()// we take the first existing order as example
const originalOrder = exchange.store.orders[0];
// update price of order
const updatedOrderIds: string[] = await exchange.updateOrder({
order: originalOrder,
update: { price: 1700 },
});
// update amount of order
const updatedOrderIds: string[] = await exchange.updateOrder({
order: originalOrder,
update: { amount: 2 },
});
cancelOrders()const orders = [exchange.store.orders[0], exchange.store.orders[1]];
await exchange.cancelOrders(orders);
cancelSymbolOrders()await exchange.cancelSymbolOrders("BTCUSDT");
cancelAllOrders()await exchange.cancelAllOrders();
setLeverage()await exchange.setLeverage("BTCUSDT", 125);
setAllLeverage()await exchange.setAllLeverage(100);
changePositionMode()// switch hedge-mode
await exchange.changePositionMode(true);
// switch one-way
await exchange.changePositionMode(false);
nuke()await exchange.nuke();
dispose()await exchange.dispose();
Because of nanoid package, in next.config.js add:
transpilePackages: ['safe-cex'],
experimental: {
esmExternals: 'loose',
}
If you found this project interesting or useful, create accounts with my referral links:
Or buy me a coffee with a crypto donation:
0xFF2da578C73bC694fd767A1CC77160002C2003E6Feel free to create issues, PRs and start a discussion ❤️
FAQs
[](https://badge.fury.io/js/safe-cex)  
We found that excex demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.