import fetch from "cross-fetch";
import { ApiError } from "../utils/errors";
async function _fetch(input, init) {
    let retry = 3;
    let err;
    while (retry--) {
        try {
            const res = await fetch(input, init);
            const clonedRes = res.clone();
            return clonedRes;
        }
        catch (error) {
            err = error;
        }
    }
    throw err;
}
export class Biconomy {
    _relayerUrl;
    _apiKey;
    _apiId;
    constructor(_relayerUrl, _apiKey, _apiId) {
        this._relayerUrl = _relayerUrl;
        this._apiKey = _apiKey;
        this._apiId = _apiId;
    }
    async getForwarderDomainDetails(args, overrides = {}) {
        const url = `${overrides.relayerUrl || this._relayerUrl}/api/v2/meta-tx/systemInfo?networkId=${args.chainId}`;
        const response = await _fetch(url, { method: "GET" });
        if (!response.ok) {
            let message;
            try {
                const jsonResponse = await response.json();
                message = JSON.stringify(jsonResponse);
            }
            catch {
                message = response.statusText;
            }
            throw new ApiError(response.status, `Failed to relay tx: ${message}`);
        }
        const txResponse = await response.json();
        return txResponse?.forwarderDomainDetails;
    }
    async relayTransaction(args, overrides = {}) {
        const url = `${overrides.relayerUrl || this._relayerUrl}/api/v2/meta-tx/native`;
        const response = await _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({
                ...args,
                apiId: overrides.apiId || this._apiId
            })
        });
        if (!response.ok) {
            let message;
            try {
                const jsonResponse = await response.json();
                message = JSON.stringify(jsonResponse);
            }
            catch {
                message = response.statusText;
            }
            throw new ApiError(response.status, `Failed to relay tx: ${message}`);
        }
        const txResponse = (await response.json());
        if (!txResponse.txHash) {
            throw new ApiError(txResponse.flag || txResponse.code, txResponse.log || txResponse.message);
        }
        return txResponse;
    }
    async getResubmitted(args, overrides = {}) {
        const url = `${overrides.relayerUrl || this._relayerUrl}/api/v1/meta-tx/resubmitted?networkId=${args.networkId}&transactionHash=${args.transactionHash}`;
        const response = await _fetch(url, {
            method: "GET",
            headers: {
                "content-type": "application/json;charset=UTF-8",
                "Access-Control-Allow-Origin": "*"
            }
        });
        if (!response.ok) {
            throw new ApiError(response.status, `Failed to get resubmitted tx: ${response.statusText}`);
        }
        return response.json();
    }
    async wait(args, overrides = {}) {
        let pending = true;
        let resubmittedResponse;
        while (pending) {
            resubmittedResponse = await this.getResubmitted(args, overrides);
            pending = resubmittedResponse.data.newStatus === "PENDING";
            if (pending) {
                await new Promise((resolve) => {
                    setTimeout(resolve, 1000);
                });
            }
        }
        return resubmittedResponse;
    }
    async check(args = {}) {
        const url = `${this._relayerUrl}/ready?apiKey=${this._apiKey || ""}&apiId=${this._apiId || ""}&contract=${args.contract || ""}`;
        try {
            const response = await _fetch(url, {
                method: "GET",
                headers: {
                    "content-type": "application/json;charset=UTF-8",
                    "Access-Control-Allow-Origin": "*"
                }
            });
            if (!response.ok) {
                return false;
            }
            const json = (await response.json());
            return json?.ready || false;
        }
        catch (e) {
            return false;
        }
    }
}
//# sourceMappingURL=biconomy.js.map