"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var assert_1 = tslib_1.__importDefault(require("assert"));
function makeKey(tx) {
    return JSON.stringify(Object.entries(tx).map(function (_a) {
        var key = _a[0], value = _a[1];
        return [key, (value || "").toString()];
    }));
}
exports.default = (function (config, signer, emit) {
    if (emit === void 0) { emit = function () { return null; }; }
    (0, assert_1.default)(signer.provider, "signer requires a provider, use signer.connect(provider)");
    var _a = config.confirmations, confirmations = _a === void 0 ? 3 : _a;
    var requests = new Map();
    var submissions = new Map();
    var mined = new Map();
    function request(unsignedTx) {
        var populated = unsignedTx;
        var key = makeKey(populated);
        (0, assert_1.default)(!requests.has(key), "Transaction already in progress");
        requests.set(key, populated);
        return key;
    }
    function processRequest(key) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var request, sent, err_1;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        request = requests.get(key);
                        (0, assert_1.default)(request, "invalid request");
                        requests.delete(key);
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 3, , 4]);
                        return [4, signer.sendTransaction(request)];
                    case 2:
                        sent = _a.sent();
                        submissions.set(key, sent.hash);
                        emit("submitted", key, sent.hash);
                        return [3, 4];
                    case 3:
                        err_1 = _a.sent();
                        emit("error", key, err_1);
                        return [3, 4];
                    case 4: return [2];
                }
            });
        });
    }
    function processSubmission(key) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var hash, receipt;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        hash = submissions.get(key);
                        (0, assert_1.default)(hash, "invalid submission");
                        (0, assert_1.default)(signer.provider, "signer requires a provider, use signer.connect(provider)");
                        return [4, signer.provider.getTransactionReceipt(hash).catch(function () { return undefined; })];
                    case 1:
                        receipt = _a.sent();
                        if (receipt == null)
                            return [2];
                        if (receipt.confirmations < confirmations)
                            return [2];
                        submissions.delete(key);
                        mined.set(key, receipt);
                        emit("mined", key, receipt);
                        return [2];
                }
            });
        });
    }
    function isMined(key) {
        return Promise.resolve(mined.get(key));
    }
    function update() {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _i, _a, key, _b, _c, key;
            return tslib_1.__generator(this, function (_d) {
                switch (_d.label) {
                    case 0:
                        _i = 0, _a = Array.from(requests.keys());
                        _d.label = 1;
                    case 1:
                        if (!(_i < _a.length)) return [3, 4];
                        key = _a[_i];
                        return [4, processRequest(key)];
                    case 2:
                        _d.sent();
                        _d.label = 3;
                    case 3:
                        _i++;
                        return [3, 1];
                    case 4:
                        _b = 0, _c = Array.from(submissions.keys());
                        _d.label = 5;
                    case 5:
                        if (!(_b < _c.length)) return [3, 8];
                        key = _c[_b];
                        return [4, processSubmission(key)];
                    case 6:
                        _d.sent();
                        _d.label = 7;
                    case 7:
                        _b++;
                        return [3, 5];
                    case 8: return [2];
                }
            });
        });
    }
    return {
        request: request,
        isMined: isMined,
        update: update,
    };
});
//# sourceMappingURL=transactionManager.js.map