<repo_name>MyCryptoHQ/eth-exists<file_sep>/src/utils/make-request.spec.ts
import { makeHttpRequest } from '@src/utils/make-request';
import moxios from 'moxios';

describe('makeHttpRequest tests', () => {
  beforeEach(() => moxios.install());
  afterEach(() => moxios.uninstall());

  it('should return with a successful request', done => {
    makeHttpRequest({
      addr: '',
      port: 100000,
      timeout: 5000,
      type: 'http',
    }).then(() => {
      done();
    });
    moxios.wait(() => {
      const request = moxios.requests.mostRecent();
      request.respondWith({ status: 200 });
    });
  });

  it('should return with a failed request', done => {
    makeHttpRequest({
      addr: '',
      port: 100000,
      timeout: 5000,
      type: 'http',
    }).catch(_ => {
      done();
    });
    moxios.wait(() => {
      const request = moxios.requests.mostRecent();
      request.respondWithTimeout();
    });
  });
});
<file_sep>/src/utils/node-exists.ts
/**
 *
 * @description Checks if the current engine is nodejs
 * @returns {boolean}
 */
function nodeExists(): boolean {
  return process.toString() === '[object process]';
}
<file_sep>/src/utils/make-request.ts
import axios, { AxiosResponse } from 'axios';
import WebSocket from 'isomorphic-ws';

export interface IHttpConfig {
  type: 'http';
  addr: string;
  port: number;
  timeout: number;
}

export function makeHttpRequest(
  config: IHttpConfig,
): Promise<AxiosResponse<any>> {
  return axios
    .post(
      `${config.addr}:${config.port}`,
      '{"jsonrpc":"2.0","method":"net_version","params":[],"id":67}',
      {
        headers: {
          'Content-Type': 'application/json;charset=UTF-8',
          'Access-Control-Allow-Origin': '*',
        },
        timeout: config.timeout,
      },
    )
    .then(r => {
      if (r.status !== 200) {
        throw Error('Request failed');
      }
      return r;
    });
}

export interface IWSConfig {
  type: 'ws';
  addr: string;
  port: number;
  timeout: number;
}

export function makeWsRequest(config: IWSConfig) {
  const url = `${config.addr}:${config.port}`;
  console.log(url);
  const socket = new WebSocket(url, {
    handshakeTimeout: config.timeout,
  });
  return new Promise((resolve, reject) => {
    let timeout: NodeJS.Timer;
    socket.onopen = () => {
      clearTimeout(timeout);
      resolve('worked');
    };

    socket.onerror = e => {
      clearTimeout(timeout);
      reject(e);
    };

    timeout = setTimeout(() => {
      reject(Error('timeout'));
    }, config.timeout);
  });
}

export type RequestConfig = IWSConfig | IHttpConfig;
export function makeRequest(config: RequestConfig) {
  switch (config.type) {
    case 'http':
      return makeHttpRequest(config);
    case 'ws':
      return makeWsRequest(config);
  }
}
<file_sep>/readme.md
# eth-exists

A library that helps check for available nodes / providers.
Useful for when you want to check a list of providers and see which ones
are online.

## Usage

```ts
import { exists } from 'mycrypto-eth-exists';

// a provider to see if they're online or not by sending a
// getNetVersion JSON-RPC request to them and checking for a response
const httpProviderToCheck: IHttpConfig = {
  type: 'http',
  addr: 'http://localhost',
  port: 8545,
  timeout: 5000,
};

// a provider to see if they're online or not by
// attempting to open a ws connection to that address
const wsProviderToCheck: IWSConfig = {
  type: 'ws',
  addr: 'ws://localhost',
  port: 8546,
  timeout: 5000,
};

// array of providers to check
const providersToCheck = [httpProviderToCheck, wsProviderToCheck];

// whether to include the default provider checks
const includeDefaults = false;

async function example() {
  // results will contain an array of providers with the same data as the initially declared
  // objects above, except they will now have a success parameter included to see if
  // they were succesfully connected to or not
  // and an error parameter of the error if it failed to connect
  const results = await exists(providersToCheck, includeDefaults);
}
```

## Provider Check Defaults

```ts
const DEFAULT_WS: IWSConfig = {
  type: 'ws',
  addr: 'ws://localhost',
  port: 8546,
  timeout: 5000,
};

const DEFAULT_HTTP: IHttpConfig = {
  type: 'http',
  addr: 'http://localhost',
  port: 8545,
  timeout: 5000,
};
```
<file_sep>/src/index.ts
import {
  IHttpConfig,
  IWSConfig,
  makeRequest,
  RequestConfig,
} from './utils/make-request';

const DEFAULT_WS: IWSConfig = {
  type: 'ws',
  addr: 'ws://localhost',
  port: 8546,
  timeout: 5000,
};

const DEFAULT_HTTP: IHttpConfig = {
  type: 'http',
  addr: 'http://localhost',
  port: 8545,
  timeout: 5000,
};

const DEFAULT_CONFIGS = [DEFAULT_HTTP, DEFAULT_WS];

export type SuccessConfig = RequestConfig & {
  success: true;
};

export type FailConfig = RequestConfig & {
  success: false;
  error: Error;
};

export interface IOptions {
  includeDefaults: boolean;
}

export function exists(
  configs: RequestConfig[] = [],
  opts: IOptions = { includeDefaults: true },
) {
  const configsToCheck = [
    ...configs,
    ...(opts.includeDefaults ? DEFAULT_CONFIGS : []),
  ];
  const result: Promise<(SuccessConfig | FailConfig)[]> = Promise.all(
    configsToCheck.map(c =>
      makeRequest(c)
        .then(() => ({ ...c, success: true as true }))
        .catch(e => ({ ...c, success: false as false, error: e as Error })),
    ),
  );

  return result;
}
