"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PorticoApi = exports.OKU_TRADE_BASE_URL = exports.RELAYER_FEE_API_URL = void 0;
const connect_sdk_1 = require("@wormhole-foundation/connect-sdk");
const axios_1 = __importDefault(require("axios"));
const abis_1 = require("./abis");
const consts_1 = require("./consts");
exports.RELAYER_FEE_API_URL = 'https://gfx.relayers.xlabs.xyz/api/v1/swap/quote';
exports.OKU_TRADE_BASE_URL = 'https://oku.trade/app';
const CREATE_ORDER_API_URL = 'https://thermae.fly.dev/api/order/create';
class PorticoApi {
    // Post the order to the portico API
    static async createOrder(network, chain, receiver, token, amount, destToken, quote, nonce) {
        try {
            const { minAmountStart, minAmountFinish } = quote.swapAmounts;
            const receiverAddress = (0, connect_sdk_1.canonicalAddress)(receiver);
            const [isStartTokenNative, startToken] = (0, connect_sdk_1.resolveWrappedToken)(network, chain, token);
            const [isFinalTokenNative, finalToken] = (0, connect_sdk_1.resolveWrappedToken)(network, receiver.chain, destToken);
            const startTokenAddress = (0, connect_sdk_1.canonicalAddress)(startToken);
            const finalTokenAddress = (0, connect_sdk_1.canonicalAddress)(finalToken);
            const sourcePorticoAddress = connect_sdk_1.contracts.portico.get(network, chain).portico;
            const destinationPorticoAddress = connect_sdk_1.contracts.portico.get(network, receiver.chain).portico;
            const startingChainId = connect_sdk_1.nativeChainIds.networkChainToNativeChainId.get(network, chain);
            const destinationChainId = connect_sdk_1.nativeChainIds.networkChainToNativeChainId.get(network, receiver.chain);
            // Create the order
            const orderRequest = {
                startingChainId: Number(startingChainId),
                startingToken: startTokenAddress.toLowerCase(),
                destinationChainId: Number(destinationChainId),
                destinationToken: finalTokenAddress.toLowerCase(),
                destinationAddress: receiverAddress,
                porticoAddress: sourcePorticoAddress,
                destinationPorticoAddress: destinationPorticoAddress,
                startingTokenAmount: amount.toString(),
                minAmountStart: minAmountStart.toString(),
                minAmountEnd: minAmountFinish.toString(),
                bridgeNonce: nonce,
                relayerFee: quote.relayerFee.toString(),
                feeTierStart: consts_1.FEE_TIER,
                feeTierEnd: consts_1.FEE_TIER,
                shouldWrapNative: isStartTokenNative,
                shouldUnwrapNative: isFinalTokenNative,
            };
            const response = await axios_1.default.post(CREATE_ORDER_API_URL, orderRequest);
            // Validate the response, not strictly necessary but if some details are wrong we want to know
            this.validateCreateOrderResponse(response.data, orderRequest);
            return response.data;
        }
        catch (e) {
            if (axios_1.default.isAxiosError(e)) {
                const message = `${e.response?.statusText}: ${e.response?.data.message}`;
                throw new Error(`Could not create order: ${message},`);
            }
            throw e;
        }
    }
    /**
     * Validates that the response from the order creation API matches the request
     * throws an error if there is a mismatch
     */
    static validateCreateOrderResponse = (response, request) => {
        if (!connect_sdk_1.tokens.isEqualCaseInsensitive(request.porticoAddress || '', response.transactionTarget)) {
            throw new Error('portico address mismatch');
        }
        const decoded = abis_1.porticoAbi.decodeFunctionData('start', response.transactionData);
        if (decoded.length !== 1 || decoded[0].length !== 10) {
            throw new Error('decoded length mismatch');
        }
        const flagSetBuffer = connect_sdk_1.encoding.hex.decode(decoded[0][0]);
        if (flagSetBuffer.length !== 32) {
            throw new Error('flag set length mismatch');
        }
        const { recipientChain, feeTierStart, feeTierFinish, flags } = connect_sdk_1.PorticoBridge.deserializeFlagSet(flagSetBuffer);
        const { shouldWrapNative, shouldUnwrapNative } = flags;
        const [_, expectedChain] = connect_sdk_1.nativeChainIds.platformNativeChainIdToNetworkChain('Evm', BigInt(request.destinationChainId));
        if (recipientChain !== (0, connect_sdk_1.toChainId)(expectedChain)) {
            throw new Error('recipient chain mismatch');
        }
        if (feeTierStart !== request.feeTierStart) {
            throw new Error('fee tier start mismatch');
        }
        if (feeTierFinish !== request.feeTierEnd) {
            throw new Error('fee tier end mismatch');
        }
        if (!!shouldWrapNative !== request.shouldWrapNative) {
            throw new Error('should wrap native mismatch');
        }
        if (!!shouldUnwrapNative !== request.shouldUnwrapNative) {
            throw new Error('should unwrap native mismatch');
        }
        const startTokenAddress = decoded[0][1];
        if (!connect_sdk_1.tokens.isEqualCaseInsensitive(startTokenAddress, request.startingToken)) {
            throw new Error('start token address mismatch');
        }
        // const startTokenId = Wormhole.chainAddress(toChain(request.startingChainId), startTokenAddress);
        // const canonicalTokenAddress: string = decoded[0][2];
        // if (!isEqualCaseInsensitive(canonicalTokenAddress, getOriginalAddress("Mainnet", startTokenId))) {
        //   throw new Error("canonical token address mismatch");
        // }
        const finalTokenAddress = decoded[0][3];
        if (!connect_sdk_1.tokens.isEqualCaseInsensitive(finalTokenAddress, request.destinationToken)) {
            throw new Error('final token address mismatch');
        }
        const recipientAddress = decoded[0][4];
        if (!connect_sdk_1.tokens.isEqualCaseInsensitive(recipientAddress, request.destinationAddress)) {
            throw new Error('recipient address mismatch');
        }
        const destinationPorticoAddress = decoded[0][5];
        if (!connect_sdk_1.tokens.isEqualCaseInsensitive(destinationPorticoAddress, request.destinationPorticoAddress || '')) {
            throw new Error('destination portico address mismatch');
        }
        const amountSpecified = decoded[0][6];
        if (amountSpecified.toString() !== request.startingTokenAmount) {
            throw new Error('amount mismatch');
        }
        const minAmountStart = decoded[0][7];
        if (minAmountStart.toString() !== request.minAmountStart) {
            throw new Error('min amount start mismatch');
        }
        const minAmountFinish = decoded[0][8];
        if (minAmountFinish.toString() !== request.minAmountEnd) {
            throw new Error('min amount finish mismatch');
        }
        const relayerFee = decoded[0][9];
        if (relayerFee.toString() !== request.relayerFee) {
            throw new Error('relayer fee mismatch');
        }
    };
    static async quoteRelayer(chain, from, to) {
        if ((0, connect_sdk_1.isNative)(from) || (0, connect_sdk_1.isNative)(to))
            throw new Error('how did you get here tho?');
        const sourceToken = connect_sdk_1.encoding.hex.encode(from.toUniversalAddress().toUint8Array(), false);
        const targetToken = connect_sdk_1.encoding.hex.encode(to.toUniversalAddress().toUint8Array(), false);
        const targetChain = (0, connect_sdk_1.toChainId)(chain);
        const request = { targetChain, sourceToken, targetToken };
        try {
            const response = await axios_1.default.post(exports.RELAYER_FEE_API_URL, request);
            return BigInt(response.data.fee);
        }
        catch (e) {
            if (axios_1.default.isAxiosError(e)) {
                throw new Error(`Error getting relayer fee: ${e.response?.statusText}`);
            }
            throw e;
        }
    }
}
exports.PorticoApi = PorticoApi;
//# sourceMappingURL=api.js.map