├── .gitignore ├── README.md ├── kucoin.js ├── lib ├── market.js ├── trade.js ├── user.js └── websockets.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kucoin-node-api 2 | 3 | This is an open source project created to utilize the Kucoin v2 API to support automated, algorithmic trading. The project was made and tested for Node 8.0+. 4 | 5 | There are no guarentees towards the stability or effectiveness of this project. Comments, 6 | contributions, stars and donations are, however, all welcome. 7 | 8 | ## Installation 9 | 10 | `npm install kucoin-node-api` 11 | 12 | Alternatively, you can clone/download the repository and import into your project by file path. 13 | 14 | ## Getting Started 15 | 16 | To begin using the API wrapper, require it, create a config object that contains your API key, Secret key and Passphrase provided by Kucoin. Then run the custom init() function with your config object as a parameter. If you are only using Public endpoints, the config object only requires the environment key/value pair. 17 | 18 | Example code is as follows: 19 | 20 | ```javascript 21 | const api = require('kucoin-node-api') 22 | 23 | const config = { 24 | apiKey: 'xXXXXXXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxXXX', 25 | secretKey: 'xxxxxxxxXXXXXXXXXXXXXxxXXXXXXXXXXXXXxxxXXX', 26 | passphrase: 'xxxxxx', 27 | environment: 'live' 28 | } 29 | 30 | api.init(config) 31 | ``` 32 | 33 | ## Using the API Wrapper 34 | 35 | Once the API wrapper object is created, you can call any of the associated functions. They will return a Promise which can be utlized with .then/.catch or async/await. Note that the Promise based approach will return directly whereas the async/await approach requires calling the function. 36 | 37 | Simple example: 38 | 39 | ```javascript 40 | // Promise based approach for getting account information (private & signed) 41 | api.getAccounts().then((r) => { 42 | console.log(r.data) 43 | }).catch((e) => { 44 | console.log(e) 45 | }) 46 | 47 | // Async/Await get account info example (private & signed) 48 | async function getAccounts() { 49 | try { 50 | let r = await api.getAccounts() 51 | console.log(r.data) 52 | } catch(err) { 53 | console.log(err) 54 | } 55 | } 56 | ``` 57 | 58 | This approach allows for more complex multi-call asynchronous functionality, especially useful for automated trading. 59 | 60 | ## Market Endpoint (Public) 61 | 62 | Public endpoints do not require an API Key, Secret Key or API Passphrase. 63 | 64 | ```javascript 65 | /* 66 | Get Symbols List 67 | GET /api/v1/symbols 68 | market = string [optional] 69 | */ 70 | api.getSymbols(market) 71 | ``` 72 | 73 | ```javascript 74 | /* 75 | Get Ticker 76 | GET /api/v1/market/orderbook/level1?symbol= 77 | symbol = string 78 | */ 79 | api.getTicker(symbol) 80 | ``` 81 | 82 | ```javascript 83 | /* 84 | Get All Tickers 85 | GET /api/v1/market/allTickers 86 | */ 87 | api.getAllTickers() 88 | ``` 89 | 90 | ```javascript 91 | /* 92 | Get 24hr Stats 93 | GET /api/v1/market/stats?symbol= 94 | symbol = string 95 | */ 96 | api.get24hrStats(symbol) 97 | ``` 98 | 99 | ```javascript 100 | /* 101 | Get Market List 102 | GET /api/v1/markets 103 | */ 104 | api.getMarketList(symbol) 105 | ``` 106 | 107 | 108 | ```javascript 109 | /* 110 | Get Part Order Book (aggregated) 111 | GET /api/v1/market/orderbook/level2_20?symbol= 112 | GET /api/v1/market/orderbook/level2_100?symbol= 113 | params = { 114 | amount: integer (20 || 100) 115 | symbol: string 116 | } 117 | */ 118 | api.getPartOrderBook(params) 119 | ``` 120 | 121 | ```javascript 122 | /* 123 | Get Full Order Book (aggregated) 124 | GET /api/v2/market/orderbook/level2?symbol= 125 | symbol = string 126 | */ 127 | api.getFullOrderBook(symbol) 128 | ``` 129 | 130 | ```javascript 131 | /* 132 | Get Full Order Book (atomic) 133 | GET /api/v1/market/orderbook/level3?symbol= 134 | symbol = string 135 | */ 136 | api.getFullOrderBookAtomic(symbol) 137 | ``` 138 | 139 | ```javascript 140 | /* 141 | Get Trade Histories 142 | GET /api/v1/market/histories?symbol= 143 | symbol = string 144 | */ 145 | api.getTradeHistories(symbol) 146 | ``` 147 | 148 | ```javascript 149 | /* 150 | Get Klines 151 | GET /api/v1/market/candles?symbol= 152 | params = { 153 | symbol: string 154 | startAt: long (unix time) 155 | endAt: long (unix time) 156 | type: enum [1min, 3min, 5min, 15min, 30min, 1hour, 2hour, 4hour, 6hour, 8hour, 12hour 1day, 1week] 157 | } 158 | */ 159 | api.getKlines(params) 160 | ``` 161 | 162 | ```javascript 163 | /* 164 | Get currencies 165 | GET /api/v1/currencies 166 | */ 167 | api.getCurrencies() 168 | ``` 169 | 170 | ```javascript 171 | /* 172 | Get currency detail 173 | GET /api/v1/currencies/{currency} 174 | currency = string 175 | */ 176 | api.getCurrency(currency) 177 | ``` 178 | 179 | ```javascript 180 | /* 181 | Get Fiat Price 182 | GET /api/v1/prices 183 | params = { 184 | base: string (e.g. 'USD') [optional] 185 | currencies: array 186 | } 187 | */ 188 | api.getFiatPrices(params) 189 | ``` 190 | 191 | ```javascript 192 | /* 193 | Server Time 194 | GET /api/v1/timestamp 195 | */ 196 | api.getServerTime() 197 | ``` 198 | 199 | ## User Endpoints (Private) 200 | 201 | ```javascript 202 | /* 203 | List Accounts 204 | GET /api/v1/accounts 205 | params = { 206 | currency: string [optional] 207 | type: string [optional] 208 | } 209 | */ 210 | api.getAccounts() 211 | ``` 212 | 213 | ```javascript 214 | /* 215 | Get Account 216 | GET /api/v1/accounts/ 217 | params = { 218 | id: accountId 219 | } 220 | */ 221 | api.getAccountById(params) 222 | ``` 223 | 224 | ```javascript 225 | /* 226 | Create Account 227 | POST /api/v1/accounts 228 | params = { 229 | type: string ['main' || 'trade'] 230 | currency: string 231 | } 232 | */ 233 | api.createAccount(params) 234 | ``` 235 | 236 | ```javascript 237 | /* 238 | Get Account Ledgers 239 | GET /api/v1/accounts//ledgers 240 | params = { 241 | id: string 242 | startAt: long (unix time) 243 | endAt: long (unix time) 244 | } 245 | */ 246 | api.getAccountLedgers(params) 247 | ``` 248 | 249 | ```javascript 250 | /* 251 | Get Holds 252 | GET /api/v1/accounts//holds 253 | params = { 254 | id: string 255 | } 256 | */ 257 | api.getHolds(params) 258 | ``` 259 | 260 | ```javascript 261 | /* 262 | Inner Transfer 263 | POST /api/accounts/inner-transfer 264 | params = { 265 | clientOid: string 266 | currency: string, 267 | from: string 268 | to: string 269 | amount: string 270 | } 271 | */ 272 | api.innerTransfer(params) 273 | ``` 274 | 275 | ```javascript 276 | /* 277 | Create Deposit Address 278 | POST /api/v1/deposit-addresses 279 | params = { 280 | currency: string 281 | } 282 | */ 283 | api.createDepositAddress(params) 284 | ``` 285 | 286 | ```javascript 287 | /* 288 | Get Deposit Address 289 | GET /api/v1/deposit-addresses?currency= 290 | params = { 291 | currency: string 292 | } 293 | */ 294 | api.getDepositAddress(params) 295 | ``` 296 | 297 | ```javascript 298 | /* 299 | Get Deposit List 300 | GET /api/v1/deposits 301 | params = { 302 | currency: string [optional] 303 | startAt: long (unix time) 304 | endAt: long (unix time) 305 | status: string [optional] 306 | } 307 | */ 308 | api.getDepositList(params) 309 | ``` 310 | 311 | ```javascript 312 | /* 313 | Get Margin Account 314 | GET /api/v1/margin/account 315 | */ 316 | api.getMarginAccount() 317 | ``` 318 | 319 | ```javascript 320 | /* 321 | Get Withdrawals List 322 | GET /api/v1/withdrawals 323 | params = { 324 | currency: string [optional] 325 | startAt: long (unix time) 326 | endAt: long (unix time) 327 | status: string [optional] 328 | } 329 | */ 330 | api.getWithdrawalsList(params) 331 | ``` 332 | 333 | ```javascript 334 | /* 335 | Get Repay Record 336 | GET /api/v1/margin/borrow/outstanding 337 | params = { 338 | currency: string [optional] 339 | currentPage: string [optional (default 1)] 340 | pageSize: string [optional (default 50)] 341 | } 342 | */ 343 | api.getRepayRecord(params) 344 | ``` 345 | 346 | 347 | ```javascript 348 | /* 349 | Get Withdrawal Quotas 350 | GET /api/v1/withdrawals/quotas 351 | params = { 352 | currency: string 353 | } 354 | */ 355 | api.getWithdrawalQuotas(params) 356 | ``` 357 | 358 | ```javascript 359 | /* 360 | Apply Withdrawal 361 | POST /api/v1/withdrawals 362 | params = { 363 | currency: string 364 | address: string 365 | amount: number 366 | memo: string [optional] 367 | isInner: boolean [optional] 368 | remark: string [optional] 369 | } 370 | */ 371 | api.applyForWithdrawal(params) 372 | ``` 373 | 374 | ```javascript 375 | /* 376 | Cancel Withdrawal 377 | DELETE /api/v1/withdrawls/ 378 | params = { 379 | withdrawalId: string 380 | } 381 | */ 382 | api.cancelWithdrawal(params) 383 | ``` 384 | 385 | ```javascript 386 | /* 387 | Get V1 Historical Withdrawals List 388 | GET /api/v1/hist-withdrawals 389 | params = { 390 | currentPage: integer [optional] 391 | pageSize: integer [optional] 392 | currency: string [optional - currency code] 393 | startAt: long (unix time) [optional] 394 | endAt: long (unix time) [optional] 395 | status: string [optional] Available value: PROCESSING, SUCCESS, and FAILURE 396 | } 397 | */ 398 | api.getV1HistoricalWithdrawls(params) 399 | ``` 400 | 401 | ```javascript 402 | /* 403 | Get V1 Historical Deposits List 404 | GET /api/v1/hist-deposits 405 | params = { 406 | currentPage: integer [optional] 407 | pageSize: integer [optional] 408 | currency: string [optional - currency code] 409 | startAt: long (unix time) [optional] 410 | endAt: long (unix time) [optional] 411 | status: string [optional] Available value: PROCESSING, SUCCESS, and FAILURE 412 | } 413 | */ 414 | api.getV1HistoricalDeposits(params) 415 | ``` 416 | 417 | ## Trade Endpoints (Private) 418 | 419 | 420 | ```javascript 421 | /* 422 | Place a new order 423 | POST /api/v1/orders 424 | Details for market order vs. limit order and params see https://docs.kucoin.com/#place-a-new-order 425 | General params 426 | params = { 427 | clientOid: string 428 | side: string ['buy' || 'sell] 429 | symbol: string 430 | type: string [optional, default: limit] 431 | remark: string [optional] 432 | stop: string [optional] - either loss or entry and needs stopPrice 433 | stopPrice: string [optional] - needed for stop 434 | stp: string [optional] (self trade prevention) 435 | price: string, 436 | size: string, 437 | timeInForce: string [optional, default is GTC] 438 | cancelAfter: long (unix time) [optional] 439 | hidden: boolean [optional] 440 | Iceberg: boolean [optional] 441 | visibleSize: string [optional] 442 | } 443 | */ 444 | api.placeOrder(params) 445 | ``` 446 | 447 | ```javascript 448 | /* 449 | Cancel an order 450 | DELETE /api/v1/orders/ 451 | params = { 452 | id: order-id 453 | } 454 | */ 455 | api.cancelOrder(params) 456 | ``` 457 | 458 | ```javascript 459 | /* 460 | Cancel all orders 461 | DELETE /api/v1/orders 462 | params = { 463 | symbol: string [optional] 464 | } 465 | */ 466 | api.cancelAllOrders(params) 467 | ``` 468 | 469 | ```javascript 470 | /* 471 | List orders 472 | GET /api/v1/orders 473 | params = { 474 | status: string [optional, default: dealt, alt: active] 475 | symbol: string [optional] 476 | side: string [optional, 'buy' || 'sell] 477 | type: string [optional, limit || limit_stop || market_stop] 478 | startAt: long (unix time) [optional] 479 | endAt: long (unix time) [optional] 480 | } 481 | */ 482 | api.getOrders(params) 483 | ``` 484 | 485 | ```javascript 486 | /* 487 | Get an order 488 | GET /api/v1/orders/ 489 | params = { 490 | id: order-id 491 | } 492 | */ 493 | api.getOrderById(params) 494 | ``` 495 | 496 | ```javascript 497 | /* 498 | List Fills 499 | GET /api/v1/fills 500 | params: { 501 | orderId: string [optional] 502 | symbol: string [optional] 503 | side: string [optional, 'buy' || 'sell] 504 | type: string [optional] 505 | startAt: long (unix time) [optional] 506 | endAt: long (unix time) [optional] 507 | } 508 | */ 509 | api.listFills(params) 510 | ``` 511 | 512 | ```javascript 513 | /* 514 | Get V1 Historical Orders List 515 | GET /api/v1/hist-orders 516 | params: { 517 | currentPage: integer [optional] 518 | pageSize: integer [optional] 519 | symbol: string [optional] 520 | startAt: long (unix time) [optional] 521 | endAt: long (unix time) [optional] 522 | side: string (buy || sell) [optional] 523 | } 524 | */ 525 | api.getV1HistoricalOrders(params) 526 | ``` 527 | ```javascript 528 | /* 529 | Get Position Details 530 | GET /api/v1/position?symbol=${symbol} 531 | Get Position List 532 | GET /api/v1/positions 533 | params: { 534 | symbol: string [optional] 535 | } 536 | */ 537 | api.getPosition() // Get Position List 538 | api.getPosition(params) // Get Position Details 539 | ``` 540 | 541 | ## Websockets 542 | 543 | The websocket component of the API wrapper is utilized by initializing websockets based on topics that match Kucoin endpoints. These include: 544 | 545 | - 'ticker' 546 | - 'allTicker' 547 | - 'symbolSnapshot' 548 | - 'marketSnapshot' 549 | - 'orderbook' 550 | - 'match' 551 | - 'fullMatch' (optional - private) 552 | - 'orders' (private) 553 | - 'balances' (private) 554 | 555 | To initialize a websocket, provide the paramaters and an event handler. A simple example is as follows: 556 | 557 | ```javascript 558 | // Parameters 559 | params = { 560 | topic: enum (see above) 561 | symbols: array (ignored if not required by the endpoint, single array element if single, multiple if desired) 562 | } 563 | 564 | // Public streaming websocket for the orderbook of the provide symbol(s) 565 | api.initSocket({topic: "orderbook", symbols: ['KCS-BTC']}, (msg) => { 566 | let data = JSON.parse(msg) 567 | console.log(data) 568 | }) 569 | 570 | // Private streaming websocket for account balances 571 | api.initSocket({topic: "balances"}, (msg) => { 572 | let data = JSON.parse(msg) 573 | console.log(data) 574 | }) 575 | ``` 576 | 577 | The event handler can be programmed to manipulate/store the returned websocket stream data as desired. 578 | 579 | ## Donation Addresses 580 | 581 | BTC: 3KvTuAnv7o2VAf4LGgg1MiDURd2DgjFGaa 582 | 583 | 584 | ETH: 0x7713a223e0e86355ac02b1e0de77695e822071cf 585 | 586 | 587 | NEO: AWngpjmoXPHiJH6rtf81brPiyPomYAqe8j 588 | 589 | Contact me for any other specific cryptocurrencies you'd prefer to use. 590 | 591 | ## License 592 | 593 | This project is open source and uses the ISC license. Feel free to utilize it in whatever way you see fit. 594 | 595 | -------------------------------------------------------------------------------- /kucoin.js: -------------------------------------------------------------------------------- 1 | const qs = require('querystring') 2 | const crypto = require('crypto') 3 | 4 | const Kucoin = { 5 | init: function(config) { 6 | let url = '' 7 | if (config.environment === 'live') { 8 | url = 'https://api.kucoin.com' 9 | } else { 10 | url = 'https://openapi-sandbox.kucoin.com' 11 | } 12 | this.environment = config.environment 13 | this.baseURL = url 14 | this.secretKey = config.secretKey 15 | this.apiKey = config.apiKey 16 | this.passphrase = config.passphrase 17 | const User = require('./lib/user') 18 | const Market = require('./lib/market') 19 | const Trade = require('./lib/trade') 20 | const Sockets = require('./lib/websockets') 21 | Object.assign(this, User, Market, Trade, Sockets) 22 | }, 23 | sign: function(endpoint, params, method) { 24 | let header = { 25 | headers: { 26 | 'Content-Type': 'application/json' 27 | } 28 | } 29 | let nonce = Date.now() + '' 30 | let strForSign = '' 31 | if (method === 'GET' || method === 'DELETE') { 32 | strForSign = nonce + method + endpoint + this.formatQuery(params) 33 | } else { 34 | strForSign = nonce + method + endpoint + JSON.stringify(params) 35 | } 36 | let signatureResult = crypto.createHmac('sha256', this.secretKey) 37 | .update(strForSign) 38 | .digest('base64') 39 | let passphraseResult = crypto.createHmac('sha256', this.secretKey) 40 | .update(this.passphrase) 41 | .digest('base64') 42 | header.headers['KC-API-SIGN'] = signatureResult 43 | header.headers['KC-API-TIMESTAMP'] = nonce 44 | header.headers['KC-API-KEY'] = this.apiKey 45 | header.headers['KC-API-PASSPHRASE'] = passphraseResult 46 | header.headers['KC-API-KEY-VERSION'] = 2 47 | return header 48 | }, 49 | formatQuery: function(queryObj) { 50 | if (JSON.stringify(queryObj).length !== 2) { 51 | return '?' + qs.stringify(queryObj) 52 | } else { 53 | return '' 54 | } 55 | } 56 | } 57 | 58 | module.exports = Kucoin -------------------------------------------------------------------------------- /lib/market.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios') 2 | 3 | const Market = {} 4 | 5 | /* 6 | Get Symbols List 7 | GET /api/v1/symbols 8 | market = string [optional] 9 | */ 10 | Market.getSymbols = async function(market = "") { 11 | let endpoint = "" 12 | if (market != "") { 13 | endpoint = `/api/v1/symbols?market=${market}` 14 | } else { 15 | endpoint = "/api/v1/symbols" 16 | } 17 | let url = this.baseURL + endpoint 18 | let result = await axios.get(url) 19 | return result.data 20 | } 21 | 22 | /* 23 | Get Ticker 24 | GET /api/v1/market/orderbook/level1?symbol= 25 | symbol = string 26 | */ 27 | Market.getTicker = async function(symbol) { 28 | let endpoint = `/api/v1/market/orderbook/level1?symbol=${symbol}` 29 | let url = this.baseURL + endpoint 30 | let result = await axios.get(url) 31 | return result.data 32 | } 33 | 34 | /* 35 | Get All Tickers 36 | GET /api/v1/market/allTickers 37 | */ 38 | Market.getAllTickers = async function() { 39 | let endpoint = '/api/v1/market/allTickers' 40 | let url = this.baseURL + endpoint 41 | let result = await axios.get(url) 42 | return result.data 43 | } 44 | 45 | /* 46 | Get 24hr Stats 47 | GET /api/v1/market/stats?symbol= 48 | symbol = string 49 | */ 50 | Market.get24hrStats = async function(symbol) { 51 | let endpoint = `/api/v1/market/stats?symbol=${symbol}` 52 | let url = this.baseURL + endpoint 53 | let result = await axios.get(url) 54 | return result.data 55 | } 56 | 57 | /* 58 | Get Market List 59 | GET /api/v1/markets 60 | */ 61 | Market.getMarketList = async function() { 62 | let endpoint = '/api/v1/markets' 63 | let url = this.baseURL + endpoint 64 | let result = await axios.get(url) 65 | return result.data 66 | } 67 | 68 | /* 69 | Get Part Order Book (aggregated) 70 | GET /api/v1/market/orderbook/level2_20?symbol= 71 | GET /api/v1/market/orderbook/level2_100?symbol= 72 | params = { 73 | amount: integer (20 || 100) 74 | symbol: string 75 | } 76 | */ 77 | Market.getPartOrderBook = async function(params) { 78 | let endpoint = `/api/v1/market/orderbook/level2_${params.amount}?symbol=${params.symbol}` 79 | let url = this.baseURL + endpoint 80 | let result = await axios.get(url) 81 | return result.data 82 | } 83 | 84 | /* 85 | Get Full Order Book (aggregated) 86 | GET /api/v1/market/orderbook/level2?symbol= 87 | symbol = string 88 | */ 89 | Market.getOrderBook = async function(symbol) { 90 | let endpoint = `/api/v1/market/orderbook/level2?symbol=${symbol}` 91 | let url = this.baseURL + endpoint 92 | let result = await axios.get(url) 93 | return result.data 94 | } 95 | 96 | /* 97 | Get Full Order Book (aggregated) 98 | GET /api/v2/market/orderbook/level2?symbol= 99 | symbol = string 100 | */ 101 | Market.getFullOrderBook = async function(symbol) { 102 | let endpoint = `/api/v3/market/orderbook/level2?symbol=${symbol}` 103 | let url = this.baseURL + endpoint 104 | let result = await axios.get(url) 105 | return result.data 106 | } 107 | 108 | /* 109 | Get Full Order Book (atomic) 110 | GET /api/v1/market/orderbook/level3?symbol= 111 | symbol = string 112 | */ 113 | Market.getFullOrderBookAtomic = async function(symbol) { 114 | let endpoint = `/api/v3/market/orderbook/level3?symbol=${symbol}` 115 | let url = this.baseURL + endpoint 116 | let result = await axios.get(url) 117 | return result.data 118 | } 119 | 120 | /* 121 | Get Trade Histories 122 | GET /api/v1/market/histories?symbol= 123 | symbol = string 124 | */ 125 | Market.getTradeHistories = async function(symbol) { 126 | let endpoint = `/api/v1/market/histories?symbol=${symbol}` 127 | let url = this.baseURL + endpoint 128 | let result = await axios.get(url) 129 | return result.data 130 | } 131 | 132 | /* 133 | Get Klines 134 | GET /api/v1/market/candles?symbol= 135 | params = { 136 | symbol: string 137 | startAt: long (unix time) 138 | endAt: long (unix time) 139 | type: enum [1min, 3min, 5min, 15min, 30min, 1hour, 2hour, 4hour, 6hour, 8hour, 12hour 1day, 1week] 140 | } 141 | */ 142 | Market.getKlines = async function(params) { 143 | let endpoint = '/api/v1/market/candles' 144 | params.startAt = params.startAt.toString().slice(0, 10) 145 | params.endAt = params.endAt.toString().slice(0, 10) 146 | let url = this.baseURL + endpoint + this.formatQuery(params) 147 | let result = await axios.get(url) 148 | return result.data 149 | } 150 | 151 | /* 152 | Get currencies 153 | GET /api/v1/currencies 154 | */ 155 | Market.getCurrencies = async function() { 156 | let endpoint = '/api/v1/currencies' 157 | let url = this.baseURL + endpoint 158 | let result = await axios.get(url) 159 | return result.data 160 | } 161 | 162 | /* 163 | Get currency detail 164 | GET /api/v1/currencies/{currency} 165 | currency = string 166 | */ 167 | Market.getCurrency = async function(currency) { 168 | let endpoint = `/api/v1/currencies/${currency}` 169 | let url = this.baseURL + endpoint 170 | let result = await axios.get(url) 171 | return result.data 172 | } 173 | 174 | /* 175 | Get Fiat Price 176 | GET /api/v1/prices 177 | params = { 178 | base: string (e.g. 'USD') [optional] 179 | currencies: array 180 | } 181 | */ 182 | Market.getFiatPrice = async function(params) { 183 | let endpoint = '/api/v1/prices' 184 | let url = this.baseURL + endpoint + this.formatQuery(params) 185 | let result = await axios.get(url) 186 | return result.data 187 | } 188 | 189 | /* 190 | Server Time 191 | GET /api/v1/timestamp 192 | */ 193 | Market.getServerTime = async function() { 194 | let endpoint = '/api/v1/timestamp' 195 | let url = this.baseURL + endpoint 196 | let result = await axios.get(url) 197 | return result.data 198 | } 199 | 200 | module.exports = Market -------------------------------------------------------------------------------- /lib/trade.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios') 2 | 3 | const Trade = {} 4 | 5 | /* 6 | Place a new order 7 | POST /api/v1/orders 8 | Details for market order vs. limit order and params see https://docs.kucoin.com/#place-a-new-order 9 | General params 10 | params = { 11 | clientOid: string 12 | side: string ['buy' || 'sell] 13 | symbol: string 14 | type: string [optional, default: limit] 15 | remark: string [optional] 16 | stop: string [optional] - either loss or entry and needs stopPrice 17 | stopPrice: string [optional] - needed for stop 18 | stp: string [optional] (self trade prevention) 19 | price: string, 20 | size: string, 21 | timeInForce: string [optional, default is GTC] 22 | cancelAfter: long (unix time) [optional] 23 | hidden: boolean [optional] 24 | Iceberg: boolean [optional] 25 | visibleSize: string [optional] 26 | } 27 | */ 28 | Trade.placeOrder = async function (params) { 29 | let endpoint = '/api/v1/orders' 30 | let url = this.baseURL + endpoint 31 | let result = await axios.post(url, params, this.sign(endpoint, params, 'POST')) 32 | return result.data 33 | } 34 | 35 | /* 36 | Cancel an order 37 | DELETE /api/v1/orders/ 38 | params = { 39 | id: order-id 40 | } 41 | */ 42 | Trade.cancelOrder = async function (params) { 43 | let endpoint = '/api/v1/orders/' + params.id 44 | delete params.id 45 | let url = this.baseURL + endpoint 46 | let result = await axios.delete(url, this.sign(endpoint, params, 'DELETE')) 47 | return result.data 48 | } 49 | 50 | /* 51 | Cancel all orders 52 | DELETE /api/v1/orders 53 | params = { 54 | symbol: string [optional] 55 | } 56 | */ 57 | Trade.cancelAllOrders = async function (params) { 58 | let endpoint = '/api/v1/orders' 59 | let url = this.baseURL + endpoint 60 | let result = await axios.delete(url, this.sign(endpoint, params, 'DELETE')) 61 | return result.data 62 | } 63 | 64 | /* 65 | List orders 66 | GET /api/v1/orders 67 | params = { 68 | status: string [optional, default: dealt, alt: active] 69 | symbol: string [optional] 70 | side: string [optional, 'buy' || 'sell] 71 | type: string [optional, limit || limit_stop || market_stop] 72 | startAt: long (unix time) [optional] 73 | endAt: long (unix time) [optional] 74 | } 75 | */ 76 | Trade.getOrders = async function (params = {}) { 77 | let endpoint = '/api/v1/orders' 78 | let url = this.baseURL + endpoint + this.formatQuery(params) 79 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 80 | return result.data 81 | } 82 | 83 | /* 84 | Get an order 85 | GET /api/v1/orders/ 86 | params = { 87 | id: order-id 88 | } 89 | */ 90 | Trade.getOrderById = async function (params) { 91 | let endpoint = '/api/v1/orders/' + params.id 92 | delete params.id 93 | let url = this.baseURL + endpoint 94 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 95 | return result.data 96 | } 97 | 98 | /* 99 | List Fills 100 | GET /api/v1/fills 101 | params: { 102 | orderId: string [optional] 103 | symbol: string [optional] 104 | side: string [optional, 'buy' || 'sell] 105 | type: string [optional] 106 | startAt: long (unix time) [optional] 107 | endAt: long (unix time) [optional] 108 | } 109 | */ 110 | Trade.listFills = async function (params = {}) { 111 | let endpoint = '/api/v1/fills' 112 | let url = this.baseURL + endpoint + this.formatQuery(params) 113 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 114 | return result.data 115 | } 116 | 117 | /* 118 | List Your Recent Fills: max 1000 fills in the last 24 hours, all symbols 119 | GET /api/v1/limit/fills 120 | */ 121 | Trade.recentFills = async function (params = {}) { 122 | let endpoint = '/api/v1/limit/fills' 123 | let url = this.baseURL + endpoint + this.formatQuery(params) 124 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 125 | return result.data 126 | } 127 | 128 | /* 129 | Get V1 Historical Orders List 130 | GET /api/v1/hist-orders 131 | params: { 132 | currentPage: integer [optional] 133 | pageSize: integer [optional] 134 | symbol: string [optional] 135 | startAt: long (unix time) [optional] 136 | endAt: long (unix time) [optional] 137 | side: string (buy || sell) [optional] 138 | } 139 | */ 140 | Trade.getV1HistoricalOrders = async function (params = {}) { 141 | let endpoint = '/api/v1/hist-orders' 142 | let url = this.baseURL + endpoint + this.formatQuery(params) 143 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 144 | return result.data 145 | } 146 | 147 | /* 148 | Get Position Details 149 | GET /api/v1/position?symbol=${symbol} 150 | Get Position List 151 | GET /api/v1/positions 152 | params: { 153 | symbol: string [optional] 154 | } 155 | */ 156 | Trade.getPosition = async function (params) { 157 | let endpoint = '' 158 | if (params != "") { 159 | endpoint = `/api/v1/position?symbol=${params}` 160 | } else { 161 | endpoint = "/api/v1/positions" 162 | } 163 | let url = this.baseURL + endpoint + this.formatQuery(params) 164 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 165 | return result.data 166 | } 167 | 168 | 169 | 170 | module.exports = Trade 171 | -------------------------------------------------------------------------------- /lib/user.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios') 2 | 3 | const User = {} 4 | 5 | /* 6 | List Accounts 7 | GET /api/v1/accounts 8 | params = { 9 | currency: string [optional] 10 | type: string [optional] 11 | } 12 | */ 13 | User.getAccounts = async function(params = {}) { 14 | let endpoint = '/api/v1/accounts' 15 | let url = this.baseURL + endpoint + this.formatQuery(params) 16 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 17 | return result.data 18 | } 19 | 20 | /* 21 | Get Account 22 | GET /api/v1/accounts/ 23 | params { 24 | id: accountId 25 | } 26 | */ 27 | User.getAccountById = async function(params) { 28 | let endpoint = '/api/v1/accounts/' + params.id 29 | delete params.id 30 | let url = this.baseURL + endpoint 31 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 32 | return result.data 33 | } 34 | 35 | /* 36 | Create Account 37 | POST /api/v1/accounts 38 | params = { 39 | type: string ['main' || 'trade'] 40 | currency: string 41 | } 42 | */ 43 | User.createAccount = async function(params) { 44 | let endpoint = '/api/v1/accounts' 45 | let url = this.baseURL + endpoint 46 | let result = await axios.post(url, params, this.sign(endpoint, params, 'POST')) 47 | return result.data 48 | } 49 | 50 | /* 51 | Get Account Ledgers 52 | GET /api/v1/accounts//ledgers 53 | params = { 54 | id: string 55 | startAt: long (unix time) 56 | endAt: long (unix time) 57 | } 58 | */ 59 | User.getAccountLedgers = async function(params) { 60 | let endpoint = `/api/v1/accounts/ledgers` 61 | let url = this.baseURL + endpoint + this.formatQuery(params) 62 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 63 | return result.data 64 | } 65 | 66 | /* 67 | Get Account Ledgers 68 | GET /api/v1/accounts//ledgers 69 | params = { 70 | id: string 71 | startAt: long (unix time) 72 | endAt: long (unix time) 73 | } 74 | */ 75 | User.getAccountLedgersOld = async function(params) { 76 | let endpoint = `/api/v1/accounts/${params.id}/ledgers` 77 | delete params.accountId 78 | let url = this.baseURL + endpoint + this.formatQuery(params) 79 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 80 | return result.data 81 | } 82 | 83 | /* 84 | Get Holds 85 | GET /api/v1/accounts//holds 86 | params = { 87 | id: string 88 | } 89 | */ 90 | User.getHolds = async function(params) { 91 | let endpoint = `/api/v1/accounts/${params.id}/holds` 92 | delete params.id 93 | let url = this.baseURL + endpoint 94 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 95 | return result.data 96 | } 97 | 98 | /* 99 | Inner Transfer 100 | POST /api/accounts/inner-transfer 101 | params = { 102 | clientOid: string 103 | currency: string, 104 | from: string 105 | to: string 106 | amount: string 107 | } 108 | */ 109 | User.innerTransfer = async function(params) { 110 | let endpoint = '/api/v2/accounts/inner-transfer' 111 | let url = this.baseURL + endpoint 112 | let result = await axios.post(url, params, this.sign(endpoint, params, 'POST')) 113 | return result.data 114 | } 115 | 116 | /* 117 | Create Deposit Address 118 | POST /api/v1/deposit-addresses 119 | params = { 120 | currency: string 121 | } 122 | */ 123 | User.createDepositAddress = async function(params) { 124 | let endpoint = '/api/v1/deposit-addresses' 125 | let url = this.baseURL + endpoint 126 | let result = await axios.post(url, params, this.sign(endpoint, params, 'POST')) 127 | return result.data 128 | } 129 | 130 | /* 131 | Get Deposit Address 132 | GET /api/v1/deposit-addresses?currency= 133 | params = { 134 | currency: string 135 | } 136 | */ 137 | User.getDepositAddress = async function(params) { 138 | let endpoint = `/api/v2/deposit-addresses?currency=${params.currency}` 139 | delete params.currency 140 | let url = this.baseURL + endpoint 141 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 142 | return result.data 143 | } 144 | 145 | /* 146 | Get Repay Record 147 | GET /api/v1/margin/borrow/outstanding 148 | params = { 149 | currency: string [optional] 150 | currentPage: string [optional (default 1)] 151 | pageSize: string [optional (default 50)] 152 | } 153 | */ 154 | User.getRepayRecord = async function(params = {}) { 155 | let endpoint = `/api/v1/margin/borrow/outstanding` 156 | let url = this.baseURL + endpoint + this.formatQuery(params) 157 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 158 | return result.data 159 | } 160 | 161 | 162 | /* 163 | Get Deposit List 164 | GET /api/v1/deposits 165 | params = { 166 | currency: string [optional] 167 | startAt: long (unix time) 168 | endAt: long (unix time) 169 | status: string [optional] 170 | } 171 | */ 172 | User.getDepositList = async function(params = {}) { 173 | let endpoint = '/api/v1/deposits' 174 | let url = this.baseURL + endpoint + this.formatQuery(params) 175 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 176 | return result.data 177 | } 178 | 179 | /* 180 | Get Margin Account 181 | GET /api/v1/margin/account 182 | */ 183 | User.getMarginAccount = async function() { 184 | const endpoint = '/api/v1/margin/account' 185 | const url = this.baseURL + endpoint 186 | const result = await axios.get(url, this.sign(endpoint, "", 'GET')) 187 | return result.data 188 | } 189 | 190 | /* 191 | Get Withdrawals List 192 | GET /api/v1/withdrawals 193 | params = { 194 | currency: string [optional] 195 | startAt: long (unix time) 196 | endAt: long (unix time) 197 | status: string [optional] 198 | } 199 | */ 200 | User.getWithdrawalsList = async function(params = {}) { 201 | let endpoint = '/api/v1/withdrawals' 202 | let url = this.baseURL + endpoint + this.formatQuery(params) 203 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 204 | return result.data 205 | } 206 | 207 | /* 208 | Get Withdrawal Quotas 209 | GET /api/v1/withdrawals/quotas 210 | params = { 211 | currency: string 212 | } 213 | */ 214 | User.getWithdrawalQuotas = async function(params) { 215 | let endpoint = '/api/v1/withdrawals/quotas' 216 | let url = this.baseURL + endpoint + this.formatQuery(params) 217 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 218 | return result.data 219 | } 220 | 221 | /* 222 | Apply Withdrawal 223 | POST /api/v1/withdrawals 224 | params = { 225 | currency: string 226 | address: string 227 | amount: number 228 | memo: string [optional] 229 | isInner: boolean [optional] 230 | remark: string [optional] 231 | } 232 | */ 233 | User.applyForWithdrawal = async function(params) { 234 | let endpoint = '/api/v1/withdrawals' 235 | let url = this.baseURL + endpoint 236 | let result = await axios.post(url, params, this.sign(endpoint, params, 'POST')) 237 | return result.data 238 | } 239 | 240 | /* 241 | Cancel Withdrawal 242 | DELETE /api/v1/withdrawls/ 243 | params = { 244 | withdrawalId: string 245 | } 246 | */ 247 | User.cancelWithdrawal = async function(params) { 248 | let endpoint = '/api/v1/withdrawls/' + params.withdrawalId 249 | delete params.withdrawalId 250 | let url = this.baseURL + endpoint 251 | let result = await axios.delete(url, this.sign(endpoint, params, 'DELETE')) 252 | return result.data 253 | } 254 | 255 | /* 256 | Get V1 Historical Withdrawals List 257 | GET /api/v1/hist-withdrawals 258 | params = { 259 | currentPage: integer [optional] 260 | pageSize: integer [optional] 261 | currency: string [optional - currency code] 262 | startAt: long (unix time) [optional] 263 | endAt: long (unix time) [optional] 264 | status: string [optional] Available value: PROCESSING, SUCCESS, and FAILURE 265 | } 266 | */ 267 | User.getV1HistoricalWithdrawals = async function(params) { 268 | let endpoint = '/api/v1/hist-withdrawals' 269 | let url = this.baseURL + endpoint + this.formatQuery(params) 270 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 271 | return result.data 272 | } 273 | 274 | /* 275 | Get V1 Historical Deposits List 276 | GET /api/v1/hist-deposits 277 | params = { 278 | currentPage: integer [optional] 279 | pageSize: integer [optional] 280 | currency: string [optional - currency code] 281 | startAt: long (unix time) [optional] 282 | endAt: long (unix time) [optional] 283 | status: string [optional] Available value: PROCESSING, SUCCESS, and FAILURE 284 | } 285 | */ 286 | User.getV1HistoricalDeposits = async function(params) { 287 | let endpoint = '/api/v1/hist-deposits' 288 | let url = this.baseURL + endpoint + this.formatQuery(params) 289 | let result = await axios.get(url, this.sign(endpoint, params, 'GET')) 290 | return result.data 291 | } 292 | 293 | module.exports = User 294 | -------------------------------------------------------------------------------- /lib/websockets.js: -------------------------------------------------------------------------------- 1 | const WebSocket = require('ws') 2 | const axios = require('axios') 3 | 4 | const Sockets = {} 5 | Sockets.ws = {} 6 | Sockets.heartbeat = {} 7 | 8 | getPublicWsToken = async function(baseURL) { 9 | let endpoint = '/api/v1/bullet-public' 10 | let url = baseURL + endpoint 11 | let result = await axios.post(url, {}) 12 | return result.data 13 | } 14 | 15 | getPrivateWsToken = async function(baseURL, sign) { 16 | let endpoint = '/api/v1/bullet-private' 17 | let url = baseURL + endpoint 18 | let result = await axios.post(url, {}, sign) 19 | return result.data 20 | } 21 | 22 | getSocketEndpoint = async function(type, baseURL, environment, sign) { 23 | let r 24 | if (type == 'private') { 25 | r = await getPrivateWsToken(baseURL, sign) 26 | } else { 27 | r = await getPublicWsToken(baseURL) 28 | } 29 | let token = r.data.token 30 | let instanceServer = r.data.instanceServers[0] 31 | 32 | if(instanceServer){ 33 | if (environment === 'sandbox') { 34 | return `${instanceServer.endpoint}?token=${token}&[connectId=${Date.now()}]` 35 | } else if (environment === 'live') { 36 | return `${instanceServer.endpoint}?token=${token}&[connectId=${Date.now()}]` 37 | } 38 | }else{ 39 | throw Error("No Kucoin WS servers running") 40 | } 41 | } 42 | 43 | /* 44 | Initiate a websocket 45 | params = { 46 | topic: enum 47 | symbols: array [optional depending on topic] 48 | } 49 | eventHanlder = function 50 | */ 51 | Sockets.initSocket = async function(params, eventHandler) { 52 | try { 53 | if ( !params.sign ) params.sign = false; 54 | if ( !params.endpoint ) params.endpoint = false; 55 | let [topic, endpoint, type] = Sockets.topics( params.topic, params.symbols, params.endpoint, params.sign ) 56 | let sign = this.sign('/api/v1/bullet-private', {}, 'POST') 57 | let websocket = await getSocketEndpoint(type, this.baseURL, this.environment, sign) 58 | let ws = new WebSocket(websocket) 59 | Sockets.ws[topic] = ws 60 | ws.on('open', () => { 61 | console.log(topic + ' opening websocket connection... ') 62 | Sockets.subscribe(topic, endpoint, type, eventHandler) 63 | Sockets.ws[topic].heartbeat = setInterval(Sockets.socketHeartBeat, 20000, topic) 64 | }) 65 | ws.on('error', (error) => { 66 | Sockets.handleSocketError(error) 67 | console.log(error) 68 | }) 69 | ws.on('ping', () => { 70 | return 71 | }) 72 | ws.on('close', () => { 73 | clearInterval(Sockets.ws[topic].heartbeat) 74 | console.log(topic + ' websocket closed...') 75 | }) 76 | } catch (err) { 77 | console.log(err) 78 | } 79 | } 80 | 81 | Sockets.handleSocketError = function(error) { 82 | console.log('WebSocket error: ' + (error.code ? ' (' + error.code + ')' : '') + 83 | (error.message ? ' ' + error.message : '')) 84 | } 85 | 86 | Sockets.socketHeartBeat = function(topic) { 87 | let ws = Sockets.ws[topic] 88 | ws.ping() 89 | } 90 | 91 | Sockets.subscribe = async function(topic, endpoint, type, eventHandler) { 92 | let ws = Sockets.ws[topic] 93 | if (type === 'private') { 94 | ws.send(JSON.stringify({ 95 | id: Date.now(), 96 | type: 'subscribe', 97 | topic: endpoint, 98 | privateChannel: true, 99 | response: true 100 | })) 101 | } else { 102 | ws.send(JSON.stringify({ 103 | id: Date.now(), 104 | type: 'subscribe', 105 | topic: endpoint, 106 | response: true 107 | })) 108 | } 109 | ws.on('message', eventHandler) 110 | } 111 | 112 | Sockets.unsubscribe = async function(topic, endpoint, type, eventHandler) { 113 | let ws = Sockets.ws[topic] 114 | ws.send(JSON.stringify({ 115 | id: Date.now(), 116 | type: 'unsubscribe', 117 | topic: endpoint, 118 | response: true 119 | })) 120 | ws.on('message', eventHandler) 121 | } 122 | 123 | Sockets.topics = function( topic, symbols = [], endpoint = false, sign = false ) { 124 | if ( endpoint ) return [topic, endpoint + ( symbols.length > 0 ? ':' : '' ) + symbols.join( ',' ), sign ? 'private' : 'public'] 125 | if ( topic === 'ticker' ) { 126 | return [topic, "/market/ticker:" + symbols.join( ',' ), 'public'] 127 | } else if ( topic === 'allTicker' ) { 128 | return [topic, "/market/ticker:all", 'public'] 129 | } else if ( topic === 'symbolSnapshot' ) { 130 | return [topic, "/market/snapshot:" + symbols[0], 'public'] 131 | } else if ( topic === 'marketSnapshot' ) { 132 | return [topic, "/market/snapshot:" + symbols[0], 'public'] 133 | } else if ( topic === 'orderbook' ) { 134 | return [topic, "/market/level2:" + symbols.join( ',' ), 'public'] 135 | } else if ( topic === 'match' ) { 136 | return [topic, "/market/match:" + symbols.join( ',' ), 'public'] 137 | } else if ( topic === 'fullMatch' ) { 138 | return [topic, "/spotMarket/level3:" + symbols.join( ',' ), 'public'] 139 | } else if ( topic === 'orders' ) { 140 | return [topic, "/spotMarket/tradeOrders", 'private'] 141 | } else if ( topic === 'balances' ) { 142 | return [topic, "/account/balance", 'private'] 143 | } else if ( topic === 'depth50' ) { 144 | return [topic, "/spotMarket/level2Depth50:" + symbols.join( ',' ), 'public'] 145 | } else if ( topic === 'depth5' ) { 146 | return [topic, "/spotMarket/level2Depth5:" + symbols.join( ',' ), 'public'] 147 | } else if ( topic === 'advancedOrders' ) { 148 | return [topic, "/spotMarket/advancedOrders", 'private'] 149 | } 150 | } 151 | 152 | module.exports = Sockets 153 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kucoin-node-api", 3 | "version": "2.1.4", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "kucoin-node-api", 9 | "version": "2.1.4", 10 | "license": "ISC", 11 | "dependencies": { 12 | "axios": "^0.21.1", 13 | "ws": "^7.5.1" 14 | } 15 | }, 16 | "node_modules/axios": { 17 | "version": "0.21.2", 18 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.2.tgz", 19 | "integrity": "sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==", 20 | "dependencies": { 21 | "follow-redirects": "^1.14.0" 22 | } 23 | }, 24 | "node_modules/follow-redirects": { 25 | "version": "1.15.0", 26 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", 27 | "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==", 28 | "funding": [ 29 | { 30 | "type": "individual", 31 | "url": "https://github.com/sponsors/RubenVerborgh" 32 | } 33 | ], 34 | "engines": { 35 | "node": ">=4.0" 36 | }, 37 | "peerDependenciesMeta": { 38 | "debug": { 39 | "optional": true 40 | } 41 | } 42 | }, 43 | "node_modules/ws": { 44 | "version": "7.5.1", 45 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz", 46 | "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==", 47 | "engines": { 48 | "node": ">=8.3.0" 49 | }, 50 | "peerDependencies": { 51 | "bufferutil": "^4.0.1", 52 | "utf-8-validate": "^5.0.2" 53 | }, 54 | "peerDependenciesMeta": { 55 | "bufferutil": { 56 | "optional": true 57 | }, 58 | "utf-8-validate": { 59 | "optional": true 60 | } 61 | } 62 | } 63 | }, 64 | "dependencies": { 65 | "axios": { 66 | "version": "0.21.2", 67 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.2.tgz", 68 | "integrity": "sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==", 69 | "requires": { 70 | "follow-redirects": "^1.14.0" 71 | } 72 | }, 73 | "follow-redirects": { 74 | "version": "1.15.0", 75 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", 76 | "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==" 77 | }, 78 | "ws": { 79 | "version": "7.5.1", 80 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz", 81 | "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==", 82 | "requires": {} 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kucoin-node-api", 3 | "version": "2.1.5", 4 | "description": "Node.js KuCoin Cryptocurrency Exchange v2 API Wrapper/SDK", 5 | "main": "kucoin.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "KuCoin", 11 | "API", 12 | "v2", 13 | "cryptocurrency", 14 | "algotrading", 15 | "KCS", 16 | "SDK" 17 | ], 18 | "author": "Eric Abrahams", 19 | "license": "ISC", 20 | "dependencies": { 21 | "axios": "^0.21.1", 22 | "ws": "^7.5.1" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/escwdev/kucoin-node-api" 27 | } 28 | } 29 | --------------------------------------------------------------------------------