"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vector_types_1 = require("@connext/vector-types");
const vector_utils_1 = require("@connext/vector-utils");
const providers_1 = require("@ethersproject/providers");
const constants_1 = require("@ethersproject/constants");
const units_1 = require("@ethersproject/units");
const sinon_1 = require("sinon");
const ethReader_1 = require("./ethReader");
let ethReader;
let channelState;
let provider1337;
let provider1338;
const assertResult = (result, isError, unwrappedVal) => {
    var _a;
    if (isError) {
        vector_utils_1.expect(result.isError).to.be.true;
        if (unwrappedVal) {
            vector_utils_1.expect((_a = result.getError()) === null || _a === void 0 ? void 0 : _a.message).to.be.eq(unwrappedVal);
        }
    }
    else {
        vector_utils_1.expect(result.isError).to.be.false;
        if (unwrappedVal) {
            vector_utils_1.expect(result.getValue()).to.deep.eq(unwrappedVal);
        }
    }
};
const _txResponse = {
    chainId: 1337,
    confirmations: 1,
    data: "0x",
    from: constants_1.AddressZero,
    gasLimit: constants_1.One,
    gasPrice: constants_1.One,
    hash: vector_utils_1.mkHash(),
    nonce: 1,
    value: constants_1.Zero,
    wait: () => Promise.resolve({}),
};
const { log } = vector_utils_1.getTestLoggers("ethReader");
describe("ethReader", () => {
    const chain1337 = 1337;
    const chain1338 = 1338;
    beforeEach(() => {
        const _provider = sinon_1.createStubInstance(providers_1.JsonRpcProvider);
        _provider.getTransaction.resolves(_txResponse);
        provider1337 = _provider;
        provider1338 = _provider;
        ethReader = new ethReader_1.EthereumChainReader({
            [chain1337]: provider1337,
            [chain1338]: provider1338,
        }, log);
        const test = vector_utils_1.createTestChannelState("create");
        channelState = test.channel;
        channelState.networkContext.chainId = 1337;
    });
    afterEach(() => {
        sinon_1.restore();
        sinon_1.reset();
    });
    describe.skip("getChainProviders", () => {
        it("happy: getChainProvider", async () => {
            const result = await ethReader.getChainProviders();
            console.log(result);
        });
    });
    describe("getHydratedProviders", () => {
        it("happy: getHydratedProviders", async () => {
            const res = await ethReader.getHydratedProviders();
            vector_utils_1.expect(res.isError).to.be.false;
            vector_utils_1.expect(res.getValue()[chain1337]).to.be.eq(provider1337);
            vector_utils_1.expect(res.getValue()[chain1338]).to.be.eq(provider1338);
        });
    });
    describe("getSyncing", () => {
        it("errors if cannot get a provider", async () => {
            const chainId = 1234;
            const res = await ethReader.getSyncing(chainId);
            assertResult(res, true, vector_types_1.ChainError.reasons.ProviderNotFound);
        });
        it("error if rpc call eth_syncing errors", async () => {
            provider1337.send.rejects(new Error("fail"));
            const res = await ethReader.getSyncing(chain1337);
            assertResult(res, true, "Could not execute rpc method");
            vector_utils_1.expect(res.getError().msg).to.be.eq("Could not execute rpc method");
            vector_utils_1.expect(res.getError().context.chainId).to.be.eq(chain1337);
            vector_utils_1.expect(res.getError().context.errors[0]).to.be.eq("fail");
            vector_utils_1.expect(res.getError().context.errors[4]).to.be.eq("fail");
        });
        it("happy: getSyncing", async () => {
            const res = await ethReader.getSyncing(chain1337);
            assertResult(res, false);
        });
        it("happy: getSyncing works after one retry", async () => {
            provider1337.send.onFirstCall().rejects(new Error("fail"));
            const res = await ethReader.getSyncing(chain1337);
            assertResult(res, false);
        });
        it("happy: getSyncing works after two retry", async () => {
            provider1337.send.onFirstCall().rejects(new Error("fail"));
            provider1337.send.onSecondCall().rejects(new Error("fail"));
            const res = await ethReader.getSyncing(chain1337);
            assertResult(res, false);
        });
    });
    describe("getCode", () => {
        it("errors if cannot get a provider", async () => {
            const chainId = 1234;
            const res = await ethReader.getCode(channelState.channelAddress, chainId);
            assertResult(res, true, vector_types_1.ChainError.reasons.ProviderNotFound);
        });
        it("errors if provider getCode errors", async () => {
            provider1337.getCode.rejects(new Error("fail"));
            const res = await ethReader.getCode(channelState.channelAddress, chain1337);
            assertResult(res, true, "Could not execute rpc method");
            vector_utils_1.expect(res.getError().msg).to.be.eq("Could not execute rpc method");
            vector_utils_1.expect(res.getError().context.chainId).to.be.eq(chain1337);
            vector_utils_1.expect(res.getError().context.errors[0]).to.be.eq("fail");
            vector_utils_1.expect(res.getError().context.errors[4]).to.be.eq("fail");
        });
        it("happy: getCode", async () => {
            const res = await ethReader.getCode(channelState.channelAddress, chain1337);
            assertResult(res, false);
        });
        it("happy: getCode works after one retry", async () => {
            provider1337.getCode.onFirstCall().rejects(new Error("fail"));
            const res = await ethReader.getCode(channelState.channelAddress, chain1337);
            assertResult(res, false);
        });
        it("happy: getCode works after second retry", async () => {
            provider1337.getCode.onFirstCall().rejects(new Error("fail"));
            provider1337.getCode.onSecondCall().rejects(new Error("fail"));
            const res = await ethReader.getCode(channelState.channelAddress, chain1337);
            assertResult(res, false);
        });
    });
    describe("getChannelDispute", () => {
        it("errors if cannot get a provider", async () => {
            const chainId = 1234;
            const res = await ethReader.getChannelDispute(channelState.channelAddress, chainId);
            assertResult(res, true, vector_types_1.ChainError.reasons.ProviderNotFound);
        });
        it("errors if getCode errors", async () => {
            provider1337.getCode.rejects(new Error("fail"));
            const res = await ethReader.getChannelDispute(channelState.channelAddress, chain1337);
            assertResult(res, true, "Could not execute rpc method");
            vector_utils_1.expect(res.getError().msg).to.be.eq("Could not execute rpc method");
            vector_utils_1.expect(res.getError().context.chainId).to.be.eq(chain1337);
            vector_utils_1.expect(res.getError().context.errors[0]).to.be.eq("fail");
            vector_utils_1.expect(res.getError().context.errors[4]).to.be.eq("fail");
        });
        it("get undefined if channel is not deployed", async () => {
            provider1337.getCode.resolves("0x");
            const res = await ethReader.getChannelDispute(channelState.channelAddress, chain1337);
            assertResult(res, false);
            vector_utils_1.expect(res.getValue()).to.be.undefined;
        });
        it("error: getChannelDispute", async () => {
            provider1337.getCode.resolves("0xA");
            const res = await ethReader.getChannelDispute(channelState.channelAddress, chain1337);
            assertResult(res, true, "Could not execute rpc method");
            vector_utils_1.expect(res.getError().context.chainId).to.be.eq(chain1337);
        });
    });
    describe("getRegisteredTransferByDefinition", () => { });
    describe("getRegisteredTransferByName", () => { });
    describe("getRegisteredTransfers", () => { });
    describe("getChannelFactoryBytecode", () => { });
    describe("getChannelMastercopyAddress", () => { });
    describe("getTotalDepositedA", () => { });
    describe("getTotalDepositedB", () => { });
    describe("create", () => { });
    describe("resolve", () => { });
    describe("getChannelAddress", () => { });
    describe("getBlockNumber", () => { });
    describe("getGasPrice", () => {
        it("errors if cannot get a provider", async () => {
            const chainId = 1234;
            const res = await ethReader.getGasPrice(chainId);
            assertResult(res, true, vector_types_1.ChainError.reasons.ProviderNotFound);
        });
        it("errors if provider.getGasPrice errors", async () => {
            const errorMessage = "provider.getGasPrice errors";
            provider1337.getGasPrice.rejects(new Error(errorMessage));
            const res = await ethReader.getGasPrice(chain1337);
            assertResult(res, true);
            vector_utils_1.expect(res.getError().msg).to.be.eq("Could not execute rpc method");
            vector_utils_1.expect(res.getError().context.chainId).to.be.eq(chain1337);
            vector_utils_1.expect(res.getError().context.errors[0]).to.be.eq(errorMessage);
            vector_utils_1.expect(res.getError().context.errors[4]).to.be.eq(errorMessage);
        });
        it("happy: getGasPrice, gasPrice < minGasPrice", async () => {
            const _gasPrice = units_1.parseUnits("1", "gwei");
            provider1337.getGasPrice.resolves(_gasPrice);
            const res = await ethReader.getGasPrice(chain1337);
            console.log(res.getValue().toString());
            assertResult(res, false);
            vector_utils_1.expect(res.getValue()).to.be.eq(ethReader_1.MIN_GAS_PRICE);
        });
        it("happy: getGasPrice, gasPrice > minGasPrice", async () => {
            const _gasPrice = units_1.parseUnits("6", "gwei");
            provider1337.getGasPrice.resolves(_gasPrice);
            const res = await ethReader.getGasPrice(chain1337);
            console.log(res.getValue().toString());
            assertResult(res, false);
            vector_utils_1.expect(res.getValue()).to.be.gt(ethReader_1.MIN_GAS_PRICE);
            vector_utils_1.expect(res.getValue()).to.be.eq(_gasPrice.add(_gasPrice.mul(ethReader_1.BUMP_GAS_PRICE).div(100)));
        });
    });
    describe("estimateGas", () => { });
    describe("getTokenAllowance", () => { });
    describe("getOnchainBalance", () => { });
    describe("getDecimals", () => { });
    describe("getWithdrawalTransactionRecord", () => { });
    describe("registerChannel", () => { });
});
//# sourceMappingURL=ethReader.spec.js.map