"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Zap = void 0;
const ApiHandler_1 = require("../helper/ApiHandler");
const dzapClient_1 = __importDefault(require("../config/dzapClient"));
const logger_1 = require("../logger/logger");
class Zap {
    constructor() {
        this.ZapapiHandler = new ApiHandler_1.ApiHandler("https://zap.dzap.io/v1", {}, 10000, 2);
        this.DzapApiHandler = new ApiHandler_1.ApiHandler("https://api.dzap.io/v1", {
            "Content-Type": "application/json",
            "x-api-key": "dzap_fccf99d759e2f0dcf4693d3460be6445"
        }, 10000, 1);
    }
    stringifyForLog(value) {
        return JSON.stringify(value, (_key, currentValue) => {
            if (typeof currentValue === "bigint") {
                return currentValue.toString();
            }
            return currentValue;
        });
    }
    logApiCall(api, endpoint, payload) {
        logger_1.logger.info(`[Zap] API call -> ${api} ${endpoint}`, {
            api,
            endpoint,
            payload
        });
    }
    logApiError(api, endpoint, payload, err) {
        var _a;
        logger_1.logger.error(`[Zap] API call failed -> ${api} ${endpoint}`, {
            api,
            endpoint,
            payload,
            error: err instanceof Error ? (_a = err.stack) !== null && _a !== void 0 ? _a : err.message : this.stringifyForLog(err)
        });
    }
    buildZapPayload(srcToken, srcChainId, srcDecimals, destToken, destChainId, destDecimals, account, amount, recipient) {
        let formatted_amount = BigInt(amount) * BigInt(10 ** srcDecimals);
        let formatted_amount_string = formatted_amount.toString();
        return {
            srcToken,
            srcChainId,
            destToken,
            destChainId,
            recipient,
            slippage: 1,
            account,
            amount: formatted_amount_string,
            estimateGas: false,
        };
    }
    buildSwapPayload(srcToken, srcChainId, srcDecimals, destToken, destChainId, destDecimals, account, amount, recipient) {
        let formatted_amount = BigInt(amount) * BigInt(10 ** srcDecimals);
        let formatted_amount_string = formatted_amount.toString();
        const data = [{
                amount: formatted_amount_string,
                srcToken,
                destToken,
                sender: account,
                slippage: 1,
                destDecimals: destDecimals,
                srcDecimals: srcDecimals
            }];
        const allowedSources = [
            "sushiswap",
            "kyberSwap",
            "paraSwap",
            "bebop",
            "oneInchViaLifi",
            "enso",
            "okx",
            "uniswap"
        ];
        return {
            chainId: srcChainId,
            recipient,
            includeSwapCallData: true,
            disableEstimation: true,
            includeTxData: true,
            withOutRevert: true,
            integratorId: "dzap",
            allowedSources,
            refundee: account,
            sender: account,
            data,
            maximizeMinToAmount: true,
            simulate: true
        };
    }
    buildBridgePayload(srcToken, srcChainId, srcDecimals, destToken, destChainId, destDecimals, account, amount, recipient) {
        let formatted_amount = BigInt(amount) * BigInt(10 ** srcDecimals);
        let formatted_amount_string = formatted_amount.toString();
        const allowedSources = [
            "stargateTaxi",
            "across",
            "relayLink",
            "cctpV2",
            "usdt0Bridge",
            "gasZip",
            "mayanFinanceSwift"
        ];
        const data = [{
                amount: formatted_amount_string,
                srcToken,
                destToken,
                toChain: destChainId,
                recipient,
                slippage: 1,
                destDecimals: destDecimals,
                srcDecimals: srcDecimals
            }];
        return {
            fromChain: srcChainId,
            sender: account,
            refundee: account,
            integratorId: "dzap",
            allowedSources,
            data,
            disableEstimation: true,
            simulate: true,
        };
    }
    async callZapAPI(payload) {
        var _a, _b, _c, _d;
        this.logApiCall("dzapClient", "buildZapTxn", payload);
        try {
            const res = await dzapClient_1.default.buildZapTxn(payload);
            let call_data;
            for (let i = 0; i < res.steps.length; i += 1) {
                let step = res.steps[i];
                if (step.action === "execute" && step.data.type === "evm") {
                    call_data = step['data']['callData'];
                }
            }
            const approvalData = {
                approveTo: (_a = res === null || res === void 0 ? void 0 : res.approvalData) === null || _a === void 0 ? void 0 : _a.approveTo,
                callTo: (_b = res === null || res === void 0 ? void 0 : res.approvalData) === null || _b === void 0 ? void 0 : _b.callTo,
                amount: payload.amount,
            };
            const srcToken = {
                chainid: payload.srcChainId,
                address: payload.srcToken
            };
            const destToken = {
                chainid: payload.destChainId,
                address: payload.destToken
            };
            const providerDetails = {
                id: res === null || res === void 0 ? void 0 : res.path[0].protocol.id,
                name: res === null || res === void 0 ? void 0 : res.path[0].protocol.name,
                logo: res === null || res === void 0 ? void 0 : res.path[0].protocol.icon,
            };
            return {
                amountIn: payload.amount,
                amountOut: res.amountOut,
                srcToken: srcToken,
                destToken: destToken,
                approvalData: approvalData,
                providerDetails: providerDetails,
                callData: call_data,
                value: (_c = res === null || res === void 0 ? void 0 : res.approvalData) === null || _c === void 0 ? void 0 : _c.amount,
                callTo: (_d = res === null || res === void 0 ? void 0 : res.approvalData) === null || _d === void 0 ? void 0 : _d.callTo
            };
        }
        catch (err) {
            this.logApiError("dzapClient", "buildZapTxn", payload, err);
            return null;
        }
    }
    async callSwapAPI(payload) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
        this.logApiCall("DZap REST", "swap/buildTx/best-return", payload);
        try {
            const res = await this.DzapApiHandler.post("swap/buildTx/best-return", payload);
            const approvalData = {
                approveTo: (_c = (_b = (_a = res === null || res === void 0 ? void 0 : res.swapData) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.approveTo) !== null && _c !== void 0 ? _c : (_d = res === null || res === void 0 ? void 0 : res.transaction) === null || _d === void 0 ? void 0 : _d.to,
                callTo: (_e = res === null || res === void 0 ? void 0 : res.transaction) === null || _e === void 0 ? void 0 : _e.to,
                amount: payload.data[0].amount,
            };
            const srcToken = {
                chainid: payload.chainId,
                address: payload.data[0].srcToken
            };
            const destToken = {
                chainid: payload.chainId,
                address: payload.data[0].destToken
            };
            const providerDetails = {
                id: (_f = res === null || res === void 0 ? void 0 : res.swapData[0]) === null || _f === void 0 ? void 0 : _f.providerDetails.id,
                name: (_g = res === null || res === void 0 ? void 0 : res.swapData[0]) === null || _g === void 0 ? void 0 : _g.providerDetails.name,
                logo: (_h = res === null || res === void 0 ? void 0 : res.swapData[0]) === null || _h === void 0 ? void 0 : _h.providerDetails.icon,
            };
            return {
                amountIn: payload.data[0].amount,
                amountOut: (_j = res === null || res === void 0 ? void 0 : res.swapData[0]) === null || _j === void 0 ? void 0 : _j.toAmount,
                srcToken: srcToken,
                destToken: destToken,
                approvalData: approvalData,
                providerDetails: providerDetails,
                callData: res === null || res === void 0 ? void 0 : res.transaction.data,
                value: (_k = res === null || res === void 0 ? void 0 : res.transaction) === null || _k === void 0 ? void 0 : _k.value,
                callTo: (_l = res === null || res === void 0 ? void 0 : res.transaction) === null || _l === void 0 ? void 0 : _l.to
            };
        }
        catch (err) {
            this.logApiError("DZap REST", "swap/buildTx/best-return", payload, err);
            return null;
        }
    }
    async callBridgeAPI(payload) {
        var _a, _b, _c, _d, _e, _f, _g;
        this.logApiCall("DZap REST", "bridge/buildTx/best-return", payload);
        try {
            const res = await this.DzapApiHandler.post("bridge/buildTx/best-return", payload);
            const bridgeEntry = (_a = res === null || res === void 0 ? void 0 : res.bridgeInfo) === null || _a === void 0 ? void 0 : _a[0];
            const bridgeApproveTo = (_c = (_b = bridgeEntry === null || bridgeEntry === void 0 ? void 0 : bridgeEntry.bridgeDetails) === null || _b === void 0 ? void 0 : _b.crossChainData) === null || _c === void 0 ? void 0 : _c.approveTo;
            const approvalData = {
                approveTo: bridgeApproveTo !== null && bridgeApproveTo !== void 0 ? bridgeApproveTo : (_d = res === null || res === void 0 ? void 0 : res.transaction) === null || _d === void 0 ? void 0 : _d.to,
                callTo: (_e = res === null || res === void 0 ? void 0 : res.transaction) === null || _e === void 0 ? void 0 : _e.to,
                amount: payload.data[0].amount,
            };
            const srcToken = {
                chainid: payload.fromChain,
                address: payload.data[0].srcToken
            };
            const destToken = {
                chainid: payload.data[0].toChain,
                address: payload.data[0].destToken
            };
            const providerDetails = {
                id: bridgeEntry === null || bridgeEntry === void 0 ? void 0 : bridgeEntry.providerDetails.id,
                name: bridgeEntry === null || bridgeEntry === void 0 ? void 0 : bridgeEntry.providerDetails.name,
                logo: bridgeEntry === null || bridgeEntry === void 0 ? void 0 : bridgeEntry.providerDetails.icon,
            };
            return {
                amountIn: payload.data[0].amount,
                amountOut: bridgeEntry === null || bridgeEntry === void 0 ? void 0 : bridgeEntry.bridgeDetails.destAmount,
                srcToken: srcToken,
                destToken: destToken,
                approvalData: approvalData,
                providerDetails: providerDetails,
                callData: res === null || res === void 0 ? void 0 : res.transaction.data,
                value: (_f = res === null || res === void 0 ? void 0 : res.transaction) === null || _f === void 0 ? void 0 : _f.value,
                callTo: (_g = res === null || res === void 0 ? void 0 : res.transaction) === null || _g === void 0 ? void 0 : _g.to
            };
        }
        catch (err) {
            this.logApiError("DZap REST", "bridge/buildTx/best-return", payload, err);
            return null;
        }
    }
    async getRoute(srcToken, srcChainId, srcDecimals, destToken, destChainId, destDecimals, account, amount, recipient, type) {
        const amountStr = amount.toString();
        if (type === "zap") {
            const payload = this.buildZapPayload(srcToken, srcChainId, srcDecimals, destToken, destChainId, destDecimals, account, amountStr, recipient);
            const res = await this.callZapAPI(payload);
            return res || "Unable to retrieve route";
        }
        if (type === "swap") {
            const payloadSwap = this.buildSwapPayload(srcToken, srcChainId, srcDecimals, destToken, destChainId, destDecimals, account, amountStr, recipient);
            let res = await this.callSwapAPI(payloadSwap);
            return res || "Unable to retrieve route";
        }
        if (type === "bridge") {
            const payloadBridge = this.buildBridgePayload(srcToken, srcChainId, srcDecimals, destToken, destChainId, destDecimals, account, amountStr, recipient);
            let res = await this.callBridgeAPI(payloadBridge);
            return res || "Unable to retrieve route";
        }
        return "Invalid type";
    }
}
exports.Zap = Zap;
