import network from "@ledgerhq/live-network";
import { DEFAULT_SWAP_TIMEOUT_MS } from "../../const/timeout";
import axios from "axios";
import { LedgerAPI4xx } from "@ledgerhq/errors";
import { SwapGenericAPIError } from "../../../../errors";
import { enrichRatesResponse } from "../../utils/enrichRatesResponse";
import { isIntegrationTestEnv } from "../../utils/isIntegrationTestEnv";
import { fetchRatesMock } from "./__mocks__/fetchRates.mocks";
import { getSwapAPIBaseURL, getSwapUserIP } from "../..";
export const throwRateError = (response) => {
    // ranked errors so incases where all rates error we return
    // the highest priority error to the user.
    // lowest number is the highest rank.
    // highest number is lowest rank.
    const errorsRank = {
        SwapExchangeRateAmountTooLowOrTooHigh: 1,
        SwapExchangeRateAmountTooLow: 2,
        SwapExchangeRateAmountTooHigh: 3,
    };
    const filterLimitResponse = response.filter(rate => {
        const name = rate.error && rate.error["name"];
        return name && errorsRank[name];
    });
    if (!filterLimitResponse.length)
        throw new SwapGenericAPIError();
    // get the highest ranked error and throw it.
    const initError = filterLimitResponse[0].error;
    const error = filterLimitResponse.reduce((acc, curr) => {
        const currError = curr.error;
        if (!acc || !currError || !acc["name"] || !currError["name"])
            return acc;
        const currErrorRank = errorsRank[currError["name"]];
        const accErrorRank = errorsRank[acc["name"]];
        if (currErrorRank <= accErrorRank) {
            if (currErrorRank === 1)
                return currError;
            const currErrorLimit = currError["amount"];
            const accErrorLimit = acc["amount"];
            // Get smallest amount supported
            if (currErrorRank === 2 &&
                currErrorLimit &&
                currErrorLimit.isLessThan(accErrorLimit || Infinity)) {
                return curr.error;
            }
            // Get highest amount supported
            if (currErrorRank === 3 &&
                currErrorLimit &&
                currErrorLimit.isGreaterThan(accErrorLimit || -Infinity)) {
                return curr.error;
            }
        }
        return acc;
    }, initError);
    throw error;
};
export async function fetchRates({ providers, currencyFrom, toCurrencyId, unitTo, unitFrom, fromCurrencyAmount, }) {
    if (isIntegrationTestEnv()) {
        return Promise.resolve(enrichRatesResponse(fetchRatesMock(fromCurrencyAmount, currencyFrom), unitTo, unitFrom));
    }
    const url = new URL(`${getSwapAPIBaseURL()}/rate`);
    const requestBody = {
        from: currencyFrom,
        to: toCurrencyId,
        amountFrom: fromCurrencyAmount,
        providers: providers,
    };
    const headers = getSwapUserIP();
    try {
        const { data } = await network({
            method: "POST",
            url: url.toString(),
            timeout: DEFAULT_SWAP_TIMEOUT_MS,
            data: requestBody,
            ...(headers !== undefined ? { headers } : {}),
        });
        const filteredData = data.filter(response => ![300, 304, 306, 308].includes(response?.errorCode)); // remove backend only errors
        const enrichedResponse = enrichRatesResponse(filteredData, unitTo, unitFrom);
        const allErrored = enrichedResponse.every(res => !!res.error);
        if (allErrored) {
            throwRateError(enrichedResponse);
        }
        // if some of the rates are successful then return those.
        return enrichedResponse
            .filter(res => !res.error)
            .sort((a, b) => b.toAmount.minus(a.toAmount).toNumber());
    }
    catch (e) {
        if (axios.isAxiosError(e)) {
            if (e.code === "ECONNABORTED") {
                // TODO: LIVE-8901 (handle request timeout)
            }
        }
        if (e instanceof LedgerAPI4xx) {
            // TODO: LIVE-8901 (handle 4xx)
        }
        throw e;
    }
}
//# sourceMappingURL=fetchRates.js.map