tiagosiebler / binance

Node.js & JavaScript SDK for Binance REST APIs & WebSockets, with TypeScript & browser support, integration tests, beautification & more.
https://www.npmjs.com/package/binance
MIT License
777 stars 266 forks source link

Documentation on running in browser with webpack #144

Open HartS opened 3 years ago

HartS commented 3 years ago

Hi, I'm interested in getting this running in my browser (I know I can get around the cors issues with CORS-proxy, so I'm not too worried about that). I'm wondering if you've documented any steps to get it built with Webpack though.

tiagosiebler commented 3 years ago

Hi there - the only docs on that so far are here: https://github.com/tiagosiebler/binance#browser-usage

If you include the bundled js file with a script tag on a page, you'll have a global variable called binanceapi that should expose all parts of the library. Hope that helps you get started - would appreciate if you can help improve the docs once you've spent time with it!

HartS commented 3 years ago

Hi @tiagosiebler I'd be happy to contribute some docs and fixes as necessary.. I'm trying to get websocket data collection working.

So it appears there are some issues here due to the websocket implementation by isomorphic-ws for the browser not having a ping() method. I'm setting up the websocket in the browser with the following code:

const wsClient = new binanceapi.WebsocketClient({
  beautify: true,
  wsUrl: 'wss://stream.binance.com:9443'
});

// receive raw events
wsClient.on('message', (data) => {
  console.log('raw message received ', JSON.stringify(data, null, 2));
});

wsClient.on('open', (data) => {
  console.log('connection opened open:', data.wsKey, data.ws.target.url);
});

// receive formatted events with beautified keys. Any "known" floats stored in strings as parsed as floats.
wsClient.on('formattedMessage', (data) => {
  console.log('formattedMessage: ', data);
});

// read response to command sent via WS stream (e.g LIST_SUBSCRIPTIONS)
wsClient.on('reply', (data) => {
  console.log('log reply: ', JSON.stringify(data, null, 2));
});

// receive notification when a ws connection is reconnecting automatically
wsClient.on('reconnecting', (data) => {
  console.log('ws automatically reconnecting.... ', data?.wsKey );
});

// receive notification that a reconnection completed successfully (e.g use REST to check for missing data)
wsClient.on('reconnected', (data) => {
  console.log('ws has reconnected ', data?.wsKey );
});

wsClient.subscribeSpotTrades('BTC/USDT');

Notes:

So I was able to get a readable browser package that I could insert debug logs into by changing https://github.com/tiagosiebler/binance/blob/master/webpack/webpack.config.js#L16 from production to development

What I found was that ws.ping is failing because it doesn't exist on the ws object.

Debugging this is really painstaking though as I have to replace the silly loglevel messages I'm interested in with console.log to get output (I haven't tried actually setting up the logger with silly logging because I assume it would be too noisy... does this sound right?). If you have any guidance on how to set things up so logging works better for debugging it'd be helpful. I may see if I can monkey patch ping/pong onto the websocket object so that it works as expected as well.

tiagosiebler commented 3 years ago

Debugging this is really painstaking though as I have to replace the silly loglevel messages I'm interested in with console.log to get output (I haven't tried actually setting up the logger with silly logging because I assume it would be too noisy... does this sound right?). If you have any guidance on how to set things up so logging works better for debugging it'd be helpful. I may see if I can monkey patch ping/pong onto the websocket object so that it works as expected as well.

Thanks for spending time on this! You can override the default logger by passing your own implementation into the second parameter of the WebsocketClient constructor. There's an example in the websocket demo in the readme: https://github.com/tiagosiebler/binance#websockets

const logger = {
  ...DefaultLogger,
  silly: (...params) => { console.log(...params); },
};

const wsClient = new WebsocketClient({
  api_key: key,
  api_secret: secret,
  beautify: true,
}, logger);

Something like this should enable the silly logger again.

What I found was that ws.ping is failing because it doesn't exist on the ws object.

It must be this part that's throwing: https://github.com/tiagosiebler/binance/blob/master/src/websocket-client.ts#L216-L217

I'm not sure yet how to approach this. If I remember right, the browser websocket implementation doesn't provide ways to send the ping/pong frames: https://stackoverflow.com/questions/10585355/sending-websocket-ping-pong-frame-from-browser

The main purpose of this logic is to send something upstream at an interval and start a timer. If the server doesn't send a reply downstream before the timer expires, we assume the connection dropped and being the resurrection process (by first closing the existing connection): https://github.com/tiagosiebler/binance/blob/master/src/websocket-client.ts#L341-L344

This works well in node where those functions trigger pong frames, but an alternative will be needed for browsers where those functions don't exist... anything to trigger some kind of server response on the same stream. If it's reliable enough, it could even replace the ping/pong heartbeats.

HartS commented 3 years ago

Thanks for the detailed response @tiagosiebler ! I may try to get together a PR working to resolve the issues if I have time over the next couple of weeks.

I'm wondering how you'd feel about removing isomorphic-ws as a dependency (it hasn't been updated in 3 years) with ws on node, and either using the native browser WebSocket or a different library for the browser bundle?

I haven't investigated this too much yet, I just noticed isomorphic-ws doesn't support ping/pong, or terminate, so it might defeat the purpose of using it in the first place if there are a lot of things that have to be handled differently.

tiagosiebler commented 3 years ago

Thanks for the detailed response @tiagosiebler ! I may try to get together a PR working to resolve the issues if I have time over the next couple of weeks.

That'd be great, thanks!

I'm wondering how you'd feel about removing isomorphic-ws as a dependency (it hasn't been updated in 3 years) with ws on node, and either using the native browser WebSocket or a different library for the browser bundle?

I'm open to alternatives as long as they don't introduce unnecessary dependencies.

I haven't investigated this too much yet, I just noticed isomorphic-ws doesn't support ping/pong, or terminate, so it might defeat the purpose of using it in the first place if there are a lot of things that have to be handled differently.

The ping/pong limitation is actually due to the websocket implementation in browsers. This library just points to it, if you're in a browser environment, but the limitation comes from the browser API: https://stackoverflow.com/questions/10585355/sending-websocket-ping-pong-frame-from-browser

mr-smit commented 2 years ago

How to build browser binanceapi.js

mkdir binance && cd binance
git clone https://github.com/tiagosiebler/binance.git .
npm install
npm install webpack
npm run build
npm run pack

Go to dist/ directory where binanceapi.js is located.

because its compiled as module, you need to import it in your project like this: import './binanceapi.js';

or in html <script type="module" src="binanceapi.js"></script>

it will create a binanceapi object which you can use like this

        // or MainClient
    let binance = new binanceapi.USDMClient({
      api_key: API_KEY,
      api_secret: API_SECRET,
    });

    let balance = await binance.getBalance();
    for(let i in balance){
        if (balance[i].asset == "USDT"){
            console.log("Balance USDT: ", balance[i].balance);
            break;
        }
    }

    let wsClient = new binanceapi.WebsocketClient({
      api_key: API_KEY,
      api_secret: API_SECRET,
      beautify: true,
      disableHeartbeat: true // browser does not support Ping/Pong
    });

    wsClient.subscribeUsdFuturesUserDataStream();

    wsClient.subscribeSymbolBookTicker('BTCUSDT', 'usdm');

    wsClient.on('open', (data) => {
      console.log('Connected !');
    });

    wsClient.on('message', (data) => {
      console.log('raw message received ', JSON.stringify(data, null, 2));
    });

    wsClient.on('formattedMessage', (data) => {
      console.log('formattedMessage: ', data);
    });

    wsClient.on('reply', (data) => {
      console.log('log reply: ', JSON.stringify(data, null, 2));
    });

    wsClient.on('error', (data) => {
      console.log('ws saw error ', data?.wsKey );
    });
tiagosiebler commented 2 years ago

How to build browser binanceapi.js

mkdir binance && cd binance
git clone https://github.com/tiagosiebler/binance.git .
npm install
npm install webpack
npm run build
npm run pack

Go to dist/ directory where binanceapi.js is located.

No need to npm install webpack, it's included in the dev dependencies so it will automatically get installed when you run npm install

Sandr0oo commented 1 year ago

@tiagosiebler Help please. I want to use your SDK in the browser, but I get an error when I try to install it. How do I solve the problem? изображение