Home Reference Source

src/multiple_http_provider.js

import Web3 from "web3"

export default class MultiHttpProvider {
    // it's require to have at least one provider, the first one in list will be the main provider
    // which will be use for all request, for eth_sendRawTransaction request, it we use all providers
    // to broadcast tx
    constructor(providers, cb) {
        if (!providers || providers.length === 0){
            throw new Error("it's require at least one providers");
        }
        this._providers = providers;
        this._cb = cb;
    }
    prepareRequest(_async) {
        var request = Web3.providers.HttpProvider.prototype.prepareRequest.call(this._providers[0], _async);
        return request;
    }
    async send(payload, cb) {
        if (this._providers.length === 1 || payload.method !== "eth_sendRawTransaction") {
            return Web3.providers.HttpProvider.prototype.send.call(this._providers[0], payload, cb);
        }
        var allPromises = [];
        this._providers.map(e => {
            var p = new Promise(function (resolve, reject) {
                Web3.providers.HttpProvider.prototype.send.call(e, payload, (err, res) => {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(res);
                    }
                });
            });
            allPromises.push(p);
        });
        var userResults = [];
        var mainResult;
        for (var i = 0; i < allPromises.length; i++) {
            try {
                var r = await allPromises[i];
                if (r.error) {
                    userResults.push({ "error": r.error.message, "success": false, "provider": this._providers[i].host });
                    if (i == 0){
                        mainResult = {err: r.error}
                    }
                } else {
                    userResults.push({ "success": true, "provider": this._providers[i].host });
                    if (i == 0) {
                        mainResult = {res: r}
                    }
                }
            } catch (e) {
                userResults.push({ "error": e, "success": false, "provider": this._providers[i].host });
                if (i == 0){
                    mainResult = {err: e}
                }
            }
        }
        if (mainResult.res) {
            cb(null, mainResult.res)
        }else {
            cb(mainResult.err,null);
        }
        if (this._cb) {
            this._cb(userResults);
        }
        return undefined;
    }
}