jaggedsoft / node-binance-api

Node Binance API is an asynchronous node.js library for the Binance API designed to be easy to use.
MIT License
1.58k stars 769 forks source link

node-fetch does not work when an instance of node-binance-api has been made #841

Closed sand3r closed 2 years ago

sand3r commented 2 years ago

Edit: closing this myself. I have downgraded node-fetch locally to the previous major (2.6.7) which resolves the issue. Root cause still unknown.

Hi,

It took me a while to find this issue and now I'm stuck. Below is my test file which demonstrates what goes wrong.

Basically 'fetch' from node-fetch stops working as soon as an instance of node-binance-api has been made.

Can anyone see or explain why? I have also included my package.json and tsconfig.json file below. At the bottom is the test file. To run it, you need to have a test API key, and then run it with yarn; yarn test

$ node -v
v16.15.1

tsconfig.json

{
  "extends": "@tsconfig/node16/tsconfig.json",
  "compilerOptions": {
    /* Basic Options */
    "target": "ES2022" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
    "module": "ES2022" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    "lib": ["ES2022"] /* Specify library files to be included in the compilation. */,

    "declaration": true /* Generates corresponding '.d.ts' file. */,
    "sourceMap": true /* Generates corresponding '.map' file. */,

    "outDir": "dist" /* Redirect output structure to the directory. */,
    "rootDir": "." /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
    "composite": true /* Enable project compilation */,

    /* Module Resolution Options */
    "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,

    /* Advanced Options */
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  },
  "ts-node": {
    "esm": true,
    "experimentalSpecifierResolution": true
  },
  // "include": ["server.ts", "src/**/*.ts"],
  "exclude": ["node_modules", "dist"]
}

package.json

{
  "name": "server",
  "version": "1.0.0",
  "main": "dist/index.js",
  "license": "MIT",
  "type": "module",
  "dependencies": {
    "@cryptoledger/shared": "*",
    "crypto": "^1.0.1",
    "express": "^4.17.3",
    "lodash.clonedeep": "^4.5.0",
    "node-binance-api": "0.13.1",
    "node-fetch": "3.2.6",
    "uuid": "^8.3.2",
    "ws": "^8.5.0"
  },
  "devDependencies": {
    "@tsconfig/node16": "^1.0.3",
    "@types/express": "^4.17.13",
    "@types/jest": "^28.1.3",
    "@types/node": "^18.0.0",
    "@types/uuid": "^8.3.4",
    "jest": "^28.1.1",
    "prettier": "^2.6.0",
    "ts-jest": "^28.0.5",
    "ts-node": "^10.7.0",
    "typescript": "^4.6.2"
  },
  "scripts": {
    "build": "tsc",
    "test": "ts-node test.ts"
  }
}

test.ts

import Binance from 'node-binance-api';
import fetch from 'node-fetch';
import { config } from './config.js';

const url = 'https://testnet.binance.vision/api/v3/time';

const apiKey = config.binance.test.api.key;
const apiSecret = config.binance.test.api.secret;

// Fetch below does not work when an instance of Binance has been made.
export const nodeBinanceApi = new Binance().options({
  APIKEY: apiKey,
  APISECRET: apiSecret,
  test: true,
  useServerTime: true,
  verbose: true,
});

// Below is commented out, but this works fine when enabled.

// const prevDayStream = nodeBinanceApi.websockets.prevDay('BTCUSDT', function (error, priceData) {
//   if (error) {
//     console.log('Error from websockets.prevDay: ', error);
//   }
//   console.log('Price Data: ', priceData);
// });

// This part fails when an instance of node-binance-api has been made.
// The error is listed below, and points to the fetch part. While this
// actually works fine, as long as there is no instance of Binance.
try {
  console.log('Execute fetch');
  const request = await fetch(url, {
    method: 'GET',
    headers: {
      recvWindow: '30000',
      'Content-Type': 'application/json',
      'X-MBX-APIKEY': apiKey,
    },
  });
  const data = await request.json();
  console.log('Data: ', data);
} catch (error) {
  console.log('Error occured: ', error);

  // Error occured:  TypeError [ERR_INVALID_ARG_TYPE]: The "listener" argument must be of type function. Received an instance of Object
  //   at checkListener (node:events:259:3)
  //   at ClientRequest.once (node:events:661:3)
  //   at new ClientRequest (node:_http_client:215:10)
  //   at Object.request (node:https:353:10)
  //   at Object.<anonymous> (r/node_modules/https-proxy-agent/node_modules/agent-base/patch-core.js:25:22)
  //   at r/node_modules/socks-proxy-agent/node_modules/agent-base/patch-core.js:23:20
  //   at file://r/packages/server/node_modules/node-fetch/src/index.js:94:20
  //   at new Promise (<anonymous>)
  //   at fetch (file://r/packages/server/node_modules/node-fetch/src/index.js:49:9)
  //   at file://r/packages/server/test.ts:28:25 {
  //   code: 'ERR_INVALID_ARG_TYPE'
  // }
}

console.log('End');
sand3r commented 2 years ago

Closing this myself. I have downgraded node-fetch locally to the previous major (2.6.7) which resolves the issue. Root cause still unknown.

Eternal-Sunshine commented 1 year ago

Took a lot of time to find out my usual fetch request in another library is failing because of this exact same bug. node-binance-api is using socks-proxy-agent internally which is causing other fetch requests to fail. as demonstrated by @sand3r Please fix this bug.