"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Biconomy = void 0;
const cross_fetch_1 = __importDefault(require("cross-fetch"));
const errors_1 = require("../utils/errors");
function _fetch(input, init) {
    return __awaiter(this, void 0, void 0, function* () {
        let retry = 3;
        let err;
        while (retry--) {
            try {
                const res = yield (0, cross_fetch_1.default)(input, init);
                const clonedRes = res.clone();
                return clonedRes;
            }
            catch (error) {
                err = error;
            }
        }
        throw err;
    });
}
class Biconomy {
    constructor(_relayerUrl, _apiKey, _apiId) {
        this._relayerUrl = _relayerUrl;
        this._apiKey = _apiKey;
        this._apiId = _apiId;
    }
    getForwarderDomainDetails(args_1) {
        return __awaiter(this, arguments, void 0, function* (args, overrides = {}) {
            const url = `${overrides.relayerUrl || this._relayerUrl}/api/v2/meta-tx/systemInfo?networkId=${args.chainId}`;
            const response = yield _fetch(url, { method: "GET" });
            if (!response.ok) {
                let message;
                try {
                    const jsonResponse = yield response.json();
                    message = JSON.stringify(jsonResponse);
                }
                catch (_a) {
                    message = response.statusText;
                }
                throw new errors_1.ApiError(response.status, `Failed to relay tx: ${message}`);
            }
            const txResponse = yield response.json();
            return txResponse === null || txResponse === void 0 ? void 0 : txResponse.forwarderDomainDetails;
        });
    }
    relayTransaction(args_1) {
        return __awaiter(this, arguments, void 0, function* (args, overrides = {}) {
            const url = `${overrides.relayerUrl || this._relayerUrl}/api/v2/meta-tx/native`;
            const response = yield _fetch(url, {
                method: "POST",
                headers: {
                    "x-api-key": overrides.apiKey || this._apiKey,
                    "content-type": "application/json;charset=UTF-8",
                    "Access-Control-Allow-Origin": "*"
                },
                body: JSON.stringify(Object.assign(Object.assign({}, args), { apiId: overrides.apiId || this._apiId }))
            });
            if (!response.ok) {
                let message;
                try {
                    const jsonResponse = yield response.json();
                    message = JSON.stringify(jsonResponse);
                }
                catch (_a) {
                    message = response.statusText;
                }
                throw new errors_1.ApiError(response.status, `Failed to relay tx: ${message}`);
            }
            const txResponse = (yield response.json());
            if (!txResponse.txHash) {
                throw new errors_1.ApiError(txResponse.flag || txResponse.code, txResponse.log || txResponse.message);
            }
            return txResponse;
        });
    }
    getResubmitted(args_1) {
        return __awaiter(this, arguments, void 0, function* (args, overrides = {}) {
            const url = `${overrides.relayerUrl || this._relayerUrl}/api/v1/meta-tx/resubmitted?networkId=${args.networkId}&transactionHash=${args.transactionHash}`;
            const response = yield _fetch(url, {
                method: "GET",
                headers: {
                    "content-type": "application/json;charset=UTF-8",
                    "Access-Control-Allow-Origin": "*"
                }
            });
            if (!response.ok) {
                throw new errors_1.ApiError(response.status, `Failed to get resubmitted tx: ${response.statusText}`);
            }
            return response.json();
        });
    }
    wait(args_1) {
        return __awaiter(this, arguments, void 0, function* (args, overrides = {}) {
            let pending = true;
            let resubmittedResponse;
            while (pending) {
                resubmittedResponse = yield this.getResubmitted(args, overrides);
                pending = resubmittedResponse.data.newStatus === "PENDING";
                if (pending) {
                    yield new Promise((resolve) => {
                        setTimeout(resolve, 1000);
                    });
                }
            }
            return resubmittedResponse;
        });
    }
    check() {
        return __awaiter(this, arguments, void 0, function* (args = {}) {
            const url = `${this._relayerUrl}/ready?apiKey=${this._apiKey || ""}&apiId=${this._apiId || ""}&contract=${args.contract || ""}`;
            try {
                const response = yield _fetch(url, {
                    method: "GET",
                    headers: {
                        "content-type": "application/json;charset=UTF-8",
                        "Access-Control-Allow-Origin": "*"
                    }
                });
                if (!response.ok) {
                    return false;
                }
                const json = (yield response.json());
                return (json === null || json === void 0 ? void 0 : json.ready) || false;
            }
            catch (e) {
                return false;
            }
        });
    }
}
exports.Biconomy = Biconomy;
//# sourceMappingURL=biconomy.js.map