Skip to content

Commit

Permalink
v3.0.0rc1 release (#133)
Browse files Browse the repository at this point in the history
* v3.0.0rc1 release

* fixing import issue and update pipeline

* update example code
  • Loading branch information
2pd authored Apr 20, 2023
1 parent fa81a1e commit 995b23d
Show file tree
Hide file tree
Showing 108 changed files with 5,333 additions and 10,362 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x, 14.x, 16.x]
node-version: [14.x, 16.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
Expand All @@ -24,7 +24,7 @@ jobs:
cache: 'npm'
- run: npm install
- run: npm run standard
- run: node __tests__/websocket/testingServer.js & sleep 50 && npx jest
- run: node __tests__/websocket/testingServer.js & sleep 50 && npm run test
coverage:
runs-on: ubuntu-latest
env:
Expand All @@ -37,9 +37,9 @@ jobs:
node-version: 17.x
- run: npm install
- run: npm run standard
- run: node __tests__/websocket/testingServer.js & sleep 50 && npx jest --silent --ci --coverage --testLocationInResults --json --outputFile="report.json"
- run: node __tests__/websocket/testingServer.js & sleep 50 && npm run coverage
- uses: artiomtr/jest-coverage-report-action@v2.0-rc.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
threshold: 95
skip-step: all
skip-step: all
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
dist
docs
coverage
coverage
report.json
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## v3.0.0-rc1 - 2023-04-20

### Added
- Add Spot Websocket API

### Updated
- Redesign the Websocket Stream and rename stream methods
- Upgrade dependencies

## v2.0.1 - 2023-02-22

Expand Down
103 changes: 40 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This is a lightweight library that works as a connector to [Binance public API](
- `/sapi/*`
- Spot Websocket Market Stream
- Spot User Data Stream
- Spot Websocket API
- Inclusion of test cases and examples
- Customizable base URL
- Support request timeout and HTTP proxy (since v2)
Expand Down Expand Up @@ -239,99 +240,75 @@ There are 2 types of error that may be returned from the API server and the user

## Websocket

### Websocket Stream
```javascript
const { Spot } = require('@binance/connector')

const client = new Spot('', '', {
wsURL: 'wss://testnet.binance.vision' // If optional base URL is not provided, wsURL defaults to wss://stream.binance.com:9443
})
const { WebsocketStream } = require('@binance/connector')
const logger = new Console({ stdout: process.stdout, stderr: process.stderr })

// define callbacks for different events
const callbacks = {
open: () => client.logger.log('open'),
close: () => client.logger.log('closed'),
message: data => client.logger.log(data)
open: () => logger.debug('Connected with Websocket server'),
close: () => logger.debug('Disconnected with Websocket server'),
message: data => logger.info(data)
}
const aggTrade = client.aggTradeWS('bnbusdt', callbacks)

// unsubscribe the stream above
setTimeout(() => client.unsubscribe(aggTrade), 3000)
const websocketStreamClient = new WebsocketStream({ logger, callbacks })
// subscribe ticker stream
websocketStreamClient.ticker('bnbusdt')
// close websocket stream
setTimeout(() => websocketStreamClient.disconnect(), 6000)

// support combined stream
const combinedStreams = client.combinedStreams(['btcusdt@miniTicker', 'ethusdt@ticker'], callbacks)
```


More websocket examples are available in the `examples` folder

### Unsubscribe a Stream

Unsubscription is achieved by closing the connection. If this method is called without any connection established, the console will output a message `No connection to close.`
### Unsubscribe Websocket Stream

```javascript
// client initialization is skipped
const wsRef = client.aggTradeWS('bnbusdt', callbacks)

// The connection (bnbusdt@aggTrade) is closed after 3 secs.
setTimeout(() => client.unsubscribe(wsRef), 3000)

// unsubscribe websocket stream
websocketStreamClient.unsubscribe('bnbusdt@kline_1m')
```

### Auto Reconnect

If there is a close event not initiated by the user, the reconnection mechanism will be triggered in 5 secs.

### Ping Server

It is possible to ping server from client, and expect to receive a PONG message.
### WebSocket API

```javascript
const { WebsocketAPI } = require('@binance/connector')
const logger = new Console({ stdout: process.stdout, stderr: process.stderr })

const { Console } = require('console')
const { Spot } = require('@binance/connector')

const logger = new Console({ stdout: process.stdout, stderr: process.stderr });
const client = new Spot('', '', { logger })

// callbacks for different events
const callbacks = {
open: () => logger.info('open'),
close: () => logger.info('closed'),
open: (client) => {
logger.debug('Connected with Websocket server')
// send message to get orderbook info after connection open
client.orderbook('BTCUSDT')
client.orderbook('BNBUSDT', { limit: 10 })
},
close: () => logger.debug('Disconnected with Websocket server'),
message: data => logger.info(data)
}

const wsRef = client.userData('the_listen_key', callbacks)
const websocketAPIClient = new WebsocketAPI(null, null, { logger, callbacks })

setInterval(() => {
client.pingServer(wsRef)
}, 1000 * 10)
// disconnect the connection
setTimeout(() => websocketAPIClient.disconnect(), 20000)

```

### Custom Logger Integration
More websocket examples are available in the `examples` folder

```javascript
const { Console } = require('console')
const fs = require('fs')
const Spot = require('@binance/connector')

const output = fs.createWriteStream('./logs/stdout.log')
const errorOutput = fs.createWriteStream('./logs/stderr.log')
### Auto Reconnect

// make sure the logs/ folder is created beforehand
const logger = new Console({ stdout: output, stderr: errorOutput })
const client = new Spot('', '', {logger})
If there is a close event not initiated by the user, the reconnection mechanism will be triggered in 5 secs.

const callbacks = {
open: () => client.logger.log('open'),
close: () => client.logger.log('closed'),
message: data => client.logger.log(data)
}
### Ping Server

const wsRef = client.aggTradeWS('bnbusdt', callbacks)
setTimeout(() => client.unsubscribe(wsRef), 5000)
// check the output file
It is possible to ping server from client, and expect to receive a PONG message.

```javascript
websocketStreamClient.pingServer()
```

### Custom Logger Integration

The default logger defined in the package is [Node.js Console class](https://nodejs.org/api/console.html). Its output is sent to `process.stdout` and `process.stderr`, same as the global console.

Note that when the connection is initialized, the console outputs a list of callbacks in the form of `listen to event: <event_name>`.
Expand All @@ -355,4 +332,4 @@ Futures and Vanilla Options APIs are not supported:
- Associated Websocket Market and User Data Streams

## License
MIT
MIT
17 changes: 16 additions & 1 deletion __tests__/helpers/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* global describe, it, expect */
const { isEmptyValue, removeEmptyValue, buildQueryString, flowRight } = require('../../src/helpers/utils')
const { isEmptyValue, removeEmptyValue, buildQueryString, flowRight, sortObject } = require('../../src/helpers/utils')

describe('#isEmptyValue', () => {
it.each([
Expand Down Expand Up @@ -106,4 +106,19 @@ describe('#flowRight', () => {
expect(instanceC.functionA()).toBe(1)
expect(instanceC.functionB()).toBe(2)
})

it('should sort object by keys', () => {
const obj = {
c: 3,
b: 2,
a: 1
}
const expectedObj = {
a: 1,
b: 2,
c: 3
}

expect(sortObject(obj)).toStrictEqual(expectedObj)
})
})
31 changes: 11 additions & 20 deletions __tests__/testUtils/testSetup.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const axios = require('axios')
const nock = require('nock')
const Spot = require('../../src/spot')
const httpAdapter = require('axios/lib/adapters/http')
const WebsocketStream = require('../../src/websocketStream')
const { buildQueryString } = require('../../src/helpers/utils')

const host = 'https://api.binance.com'
axios.defaults.adapter = httpAdapter

const SpotClient = new Spot()

const filterPath = path => {
const pathList = path.split('?')
Expand Down Expand Up @@ -48,37 +48,28 @@ const nockPutMock = urlPath => responseData => {
.reply(200, responseData)
}

const SpotClient = new Spot()
const websocketStreamClient = new WebsocketStream()

const mockSubscription = (targetUrl, mockResponse) => {
SpotClient.subscribe = new Proxy(SpotClient.subscribe, {
apply: function (target, thisArg, [url, callback]) {
websocketStreamClient.subscribe = new Proxy(websocketStreamClient.subscribe, {
apply: function (target, thisArg, [url]) {
targetUrl = targetUrl.replace('?', '\\?')
if (url.match(new RegExp(`${targetUrl}$`))) {
return callback(null, mockResponse)
return mockResponse
}
return callback(new Error('URL mismatch'))
console.log(url)
return new Error('URL mismatch')
}
})
}

const mockConnection = (classInstance, streamMethod, ...args) => testScenarios => {
const messages = []
const messageCallback = (err, data) => {
if (err) messages.push(err)
else messages.push(data)
}
classInstance[streamMethod](...args, messageCallback)
return testScenarios(messages)
}

module.exports = {
nockMock,
nockPostMock,
nockDeleteMock,
nockPutMock,
buildQueryString,
mockSubscription,
mockConnection,
SpotClient
SpotClient,
websocketStreamClient
}
7 changes: 2 additions & 5 deletions __tests__/websocket/aggTrade.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
/* global describe, it, expect */
const { SpotClient, mockSubscription, mockConnection } = require('../testUtils/testSetup')
/* global describe, it */
const { mockSubscription } = require('../testUtils/testSetup')
const { mockResponse } = require('../testUtils/mockData')

describe('#aggTrade', () => {
it('should get aggregate trade data', () => {
const symbol = 'BNBUSDT'
mockSubscription(`/ws/${symbol.toLowerCase()}@aggTrade`, mockResponse)
mockConnection(SpotClient, 'aggTradeWS', symbol)(data => {
expect(data).toEqual([mockResponse])
})
})
})
10 changes: 2 additions & 8 deletions __tests__/websocket/bookTicker.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
/* global describe, it, expect */
const { SpotClient, mockSubscription, mockConnection } = require('../testUtils/testSetup')
/* global describe, it */
const { mockSubscription } = require('../testUtils/testSetup')
const { mockResponse } = require('../testUtils/mockData')

describe('#bookTicker', () => {
it('should get bookTicker data', () => {
const symbol = 'BNBUSDT'
mockSubscription(`/ws/${symbol.toLowerCase()}@bookTicker`, mockResponse)
mockConnection(SpotClient, 'bookTickerWS', symbol)(data => {
expect(data).toEqual([mockResponse])
})
})

it('should get all bookTicker data', () => {
mockSubscription('/ws/!bookTicker', mockResponse)
mockConnection(SpotClient, 'bookTickerWS', null)(data => {
expect(data).toEqual([mockResponse])
})
})
})
10 changes: 2 additions & 8 deletions __tests__/websocket/combinedStreams.test.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
/* global describe, it, expect */
const { SpotClient, mockSubscription, mockConnection } = require('../testUtils/testSetup')
/* global describe, it */
const { mockSubscription } = require('../testUtils/testSetup')
const { mockResponse } = require('../testUtils/mockData')

describe('#combinedStreams', () => {
it('should get combined stream data with single stream', () => {
const stream = 'btcusdt@miniTicker'
mockSubscription(`/stream?streams=${stream}`, mockResponse)
mockConnection(SpotClient, 'combinedStreams', stream)(data => {
expect(data).toEqual([mockResponse])
})
})

it('should get combined stream data', () => {
const streams = ['btcusdt@miniTicker', 'ethusdt@ticker']
mockSubscription(`/stream?streams=${streams.join('/')}`, mockResponse)
mockConnection(SpotClient, 'combinedStreams', streams)(data => {
expect(data).toEqual([mockResponse])
})
})
})
7 changes: 2 additions & 5 deletions __tests__/websocket/diffBookDepth.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
/* global describe, it, expect */
const { SpotClient, mockSubscription, mockConnection } = require('../testUtils/testSetup')
/* global describe, it */
const { mockSubscription } = require('../testUtils/testSetup')
const { mockResponse } = require('../testUtils/mockData')

describe('#diffBookDepth', () => {
it('should get diffBookDepth data', () => {
const symbol = 'BNBUSDT'
const speed = '1000ms'
mockSubscription(`/ws/${symbol.toLowerCase()}@depth@${speed}`, mockResponse)
mockConnection(SpotClient, 'diffBookDepth', symbol, speed)(data => {
expect(data).toEqual([mockResponse])
})
})
})
7 changes: 2 additions & 5 deletions __tests__/websocket/kline.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
/* global describe, it, expect */
const { SpotClient, mockSubscription, mockConnection } = require('../testUtils/testSetup')
/* global describe, it */
const { mockSubscription } = require('../testUtils/testSetup')
const { mockResponse } = require('../testUtils/mockData')

describe('#kline', () => {
it('should get kline data', () => {
const symbol = 'BNBUSDT'
const interval = '1m'
mockSubscription(`/ws/${symbol.toLowerCase()}@kline_${interval}`, mockResponse)
mockConnection(SpotClient, 'klineWS', symbol, interval)(data => {
expect(data).toEqual([mockResponse])
})
})
})
Loading

0 comments on commit 995b23d

Please sign in to comment.