"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CCTPV2_FINALITY_THRESHOLD_FAST = exports.CCTPV2_FINALITY_THRESHOLD_STANDARD = void 0;
exports.cctpAddressToBytes32 = cctpAddressToBytes32;
exports.cctpBytes32ToAddress = cctpBytes32ToAddress;
exports.getCctpDomainForChainId = getCctpDomainForChainId;
exports.getCctpDestinationChainFromDomain = getCctpDestinationChainFromDomain;
exports.isDepositForBurnEvent = isDepositForBurnEvent;
exports.fetchCctpV2Attestations = fetchCctpV2Attestations;
exports.getPendingAttestationStatus = getPendingAttestationStatus;
exports.hasCCTPMessageBeenProcessedEvm = hasCCTPMessageBeenProcessedEvm;
exports.getV2FastBurnAllowance = getV2FastBurnAllowance;
exports.getV2MinTransferFees = getV2MinTransferFees;
exports.fetchAttestationsForTxn = fetchAttestationsForTxn;
exports.getMessageSentVersion = getMessageSentVersion;
exports.getDepositForBurnVersion = getDepositForBurnVersion;
var tslib_1 = require("tslib");
var constants_1 = require("@across-protocol/constants");
var ethers_1 = require("ethers");
var TypeGuards_1 = require("./TypeGuards");
var axios_1 = tslib_1.__importDefault(require("axios"));
var NetworkUtils_1 = require("./NetworkUtils");
var assert_1 = tslib_1.__importDefault(require("assert"));
var BigNumberUtils_1 = require("./BigNumberUtils");
exports.CCTPV2_FINALITY_THRESHOLD_STANDARD = 2000;
exports.CCTPV2_FINALITY_THRESHOLD_FAST = 1000;
var CCTP_MESSAGE_SENT_TOPIC_HASH = ethers_1.ethers.utils.id("MessageSent(bytes)");
var CCTP_DEPOSIT_FOR_BURN_TOPIC_HASH_V1 = ethers_1.ethers.utils.id("DepositForBurn(uint64,address,uint256,address,bytes32,uint32,bytes32,bytes32)");
var CCTP_DEPOSIT_FOR_BURN_TOPIC_HASH_V2 = ethers_1.ethers.utils.id("DepositForBurn(address,uint256,address,bytes32,uint32,bytes32,bytes32,uint256,uint32,bytes)");
function cctpAddressToBytes32(address) {
    return ethers_1.ethers.utils.hexZeroPad(address, 32);
}
function cctpBytes32ToAddress(bytes32) {
    return ethers_1.ethers.utils.getAddress(ethers_1.ethers.utils.hexDataSlice(bytes32, 12));
}
function getCctpDomainForChainId(chainId) {
    var _a;
    var cctpDomain = (_a = constants_1.PUBLIC_NETWORKS[chainId]) === null || _a === void 0 ? void 0 : _a.cctpDomain;
    if (!(0, TypeGuards_1.isDefined)(cctpDomain) || cctpDomain === constants_1.CCTP_NO_DOMAIN) {
        throw new Error("No CCTP domain found for chainId: ".concat(chainId));
    }
    return cctpDomain;
}
function getCctpDestinationChainFromDomain(domain, productionNetworks) {
    if (domain === constants_1.CCTP_NO_DOMAIN) {
        throw new Error("Cannot input CCTP_NO_DOMAIN to getCctpDestinationChainFromDomain");
    }
    var networks = productionNetworks ? constants_1.PRODUCTION_NETWORKS : constants_1.TEST_NETWORKS;
    var otherNetworks = productionNetworks ? constants_1.TEST_NETWORKS : constants_1.PRODUCTION_NETWORKS;
    var chainId = Object.keys(networks).find(function (key) { return networks[Number(key)].cctpDomain.toString() === domain.toString(); });
    if (!(0, TypeGuards_1.isDefined)(chainId)) {
        var chainId_1 = Object.keys(otherNetworks).find(function (key) { return otherNetworks[Number(key)].cctpDomain.toString() === domain.toString(); });
        if (!(0, TypeGuards_1.isDefined)(chainId_1)) {
            throw new Error("No chainId found for domain: ".concat(domain));
        }
        return parseInt(chainId_1);
    }
    return parseInt(chainId);
}
function isDepositForBurnEvent(event) {
    return "amount" in event && "mintRecipient" in event && "burnToken" in event;
}
function fetchCctpV2Attestations(depositForBurnTxnHashes, sourceChainId) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var sourceDomainId, isMainnet, attestationResponses, chunkSize, i, chunk;
        var _this = this;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    sourceDomainId = getCctpDomainForChainId(sourceChainId);
                    isMainnet = (0, NetworkUtils_1.chainIsProd)(sourceChainId);
                    attestationResponses = {};
                    chunkSize = process.env.CCTP_API_REQUEST_CHUNK_SIZE ? parseInt(process.env.CCTP_API_REQUEST_CHUNK_SIZE) : 8;
                    i = 0;
                    _a.label = 1;
                case 1:
                    if (!(i < depositForBurnTxnHashes.length)) return [3, 5];
                    chunk = depositForBurnTxnHashes.slice(i, i + chunkSize);
                    return [4, Promise.all(chunk.map(function (txHash) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
                            var attestations;
                            return tslib_1.__generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0: return [4, fetchAttestationsForTxn(sourceDomainId, txHash, isMainnet)];
                                    case 1:
                                        attestations = _a.sent();
                                        attestationResponses[txHash] = attestations;
                                        return [2];
                                }
                            });
                        }); }))];
                case 2:
                    _a.sent();
                    if (!(i + chunkSize < depositForBurnTxnHashes.length)) return [3, 4];
                    return [4, new Promise(function (resolve) { return setTimeout(resolve, 1000); })];
                case 3:
                    _a.sent();
                    _a.label = 4;
                case 4:
                    i += chunkSize;
                    return [3, 1];
                case 5: return [2, attestationResponses];
            }
        });
    });
}
function getPendingAttestationStatus(attestation) {
    if (!(0, TypeGuards_1.isDefined)(attestation.attestation)) {
        return "pending";
    }
    else {
        return attestation.status === "pending_confirmations" || attestation.attestation === "PENDING"
            ? "pending"
            : "ready";
    }
}
function hasCCTPMessageBeenProcessedEvm(nonceHash, contract) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var resultingCall;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4, contract.callStatic.usedNonces(nonceHash)];
                case 1:
                    resultingCall = _a.sent();
                    return [2, (resultingCall !== null && resultingCall !== void 0 ? resultingCall : BigNumberUtils_1.bnZero).toNumber() === 1];
            }
        });
    });
}
function getV2FastBurnAllowance(isMainnet) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var httpResponse;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4, axios_1.default.get("https://iris-api".concat(isMainnet ? "" : "-sandbox", ".circle.com/v2/fastBurn/USDC/allowance"))];
                case 1:
                    httpResponse = _a.sent();
                    return [2, httpResponse.data.allowance.toString()];
            }
        });
    });
}
function getV2MinTransferFees(sourceChainId, destinationChainId) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var isMainnet, sourceDomain, destinationDomain, endpoint, httpResponse, standardFee, fastFee;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    isMainnet = (0, NetworkUtils_1.chainIsProd)(destinationChainId);
                    sourceDomain = getCctpDomainForChainId(sourceChainId);
                    destinationDomain = getCctpDomainForChainId(destinationChainId);
                    endpoint = "https://iris-api".concat(isMainnet ? "" : "-sandbox", ".circle.com/v2/burn/USDC/fees/").concat(sourceDomain, "/").concat(destinationDomain);
                    return [4, axios_1.default.get(endpoint)];
                case 1:
                    httpResponse = _a.sent();
                    standardFee = httpResponse.data.find(function (fee) { return fee.finalityThreshold === exports.CCTPV2_FINALITY_THRESHOLD_STANDARD; });
                    (0, assert_1.default)((0, TypeGuards_1.isDefined)(standardFee === null || standardFee === void 0 ? void 0 : standardFee.minimumFee), "CCTPUtils#getTransferFees: Standard fee not found in API response: ".concat(endpoint));
                    fastFee = httpResponse.data.find(function (fee) { return fee.finalityThreshold === exports.CCTPV2_FINALITY_THRESHOLD_FAST; });
                    (0, assert_1.default)((0, TypeGuards_1.isDefined)(fastFee === null || fastFee === void 0 ? void 0 : fastFee.minimumFee), "CCTPUtils#getTransferFees: Fast fee not found in API response: ".concat(endpoint));
                    return [2, {
                            standard: ethers_1.BigNumber.from(standardFee.minimumFee),
                            fast: ethers_1.BigNumber.from(fastFee.minimumFee),
                        }];
            }
        });
    });
}
function fetchAttestationsForTxn(sourceDomainId, transactionHash, isMainnet) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var httpResponse;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4, axios_1.default.get("https://iris-api".concat(isMainnet ? "" : "-sandbox", ".circle.com/v2/messages/").concat(sourceDomainId, "?transactionHash=").concat(transactionHash))];
                case 1:
                    httpResponse = _a.sent();
                    return [2, httpResponse.data];
            }
        });
    });
}
function getMessageSentVersion(log) {
    if (log.topics[0] !== CCTP_MESSAGE_SENT_TOPIC_HASH) {
        return -1;
    }
    var messageBytes = ethers_1.ethers.utils.defaultAbiCoder.decode(["bytes"], log.data)[0];
    var version = parseInt(messageBytes.slice(2, 10), 16);
    return version;
}
function getDepositForBurnVersion(log) {
    var topic = log.topics[0];
    switch (topic) {
        case CCTP_DEPOSIT_FOR_BURN_TOPIC_HASH_V1:
            return 0;
        case CCTP_DEPOSIT_FOR_BURN_TOPIC_HASH_V2:
            return 1;
        default:
            return -1;
    }
}
//# sourceMappingURL=CCTPUtils.js.map