"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SvmCpiEventsClient = void 0;
var tslib_1 = require("tslib");
var contracts_1 = require("@across-protocol/contracts");
var web3_v1_1 = require("@across-protocol/contracts/dist/src/svm/web3-v1");
var kit_1 = require("@solana/kit");
var utils_1 = require("../../utils");
var utils_2 = require("./utils");
var _1 = require("./");
var assert_1 = tslib_1.__importDefault(require("assert"));
var SvmCpiEventsClient = (function () {
    function SvmCpiEventsClient(rpc, address, eventAuthority, idl) {
        this.rpc = rpc;
        this.programAddress = address;
        this.programEventAuthority = eventAuthority;
        this.idl = idl;
    }
    SvmCpiEventsClient.create = function (rpc) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var isTestnet, programId;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, (0, utils_2.isDevnet)(rpc)];
                    case 1:
                        isTestnet = _a.sent();
                        programId = (0, contracts_1.getDeployedAddress)("SvmSpoke", (0, web3_v1_1.getSolanaChainId)(isTestnet ? "devnet" : "mainnet").toString());
                        if (!programId)
                            throw new Error("Program not found");
                        return [2, this.createFor(rpc, programId, contracts_1.SvmSpokeIdl)];
                }
            });
        });
    };
    SvmCpiEventsClient.createFor = function (rpc, programId, idl) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var programAddress, eventAuthority;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        programAddress = (0, kit_1.address)(programId);
                        return [4, (0, kit_1.getProgramDerivedAddress)({
                                programAddress: programAddress,
                                seeds: ["__event_authority"],
                            })];
                    case 1:
                        eventAuthority = (_a.sent())[0];
                        return [2, new SvmCpiEventsClient(rpc, programAddress, eventAuthority, idl)];
                }
            });
        });
    };
    SvmCpiEventsClient.prototype.queryEvents = function (eventName, fromSlot, toSlot, options) {
        if (options === void 0) { options = { limit: 1000, commitment: "confirmed" }; }
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var events;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, this.queryAllEvents(fromSlot, toSlot, options)];
                    case 1:
                        events = _a.sent();
                        return [2, events.filter(function (event) { return event.name === eventName; })];
                }
            });
        });
    };
    SvmCpiEventsClient.prototype.queryDerivedAddressEvents = function (eventName, derivedAddress, fromSlot, toSlot, options) {
        if (options === void 0) { options = { limit: 1000, commitment: "confirmed" }; }
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var events;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, this.queryAllEvents(fromSlot, toSlot, options, derivedAddress)];
                    case 1:
                        events = _a.sent();
                        return [2, events.filter(function (event) { return event.name === eventName; })];
                }
            });
        });
    };
    SvmCpiEventsClient.prototype.queryAllEvents = function (fromSlot, toSlot, options, derivedAddress) {
        if (options === void 0) { options = { limit: 1000, commitment: "confirmed" }; }
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var addressToQuery, allSignatures, hasMoreSignatures, currentOptions, signatures, filteredSignatures, eventsWithSlots;
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        addressToQuery = derivedAddress || this.programAddress;
                        allSignatures = [];
                        hasMoreSignatures = true;
                        currentOptions = options;
                        _a.label = 1;
                    case 1:
                        if (!hasMoreSignatures) return [3, 3];
                        return [4, this.rpc
                                .getSignaturesForAddress(addressToQuery, currentOptions)
                                .send()];
                    case 2:
                        signatures = _a.sent();
                        allSignatures.push.apply(allSignatures, signatures);
                        if (signatures.length > 0) {
                            currentOptions = tslib_1.__assign(tslib_1.__assign({}, currentOptions), { before: signatures[signatures.length - 1].signature });
                        }
                        if (fromSlot && allSignatures.length > 0 && allSignatures[allSignatures.length - 1].slot < fromSlot) {
                            hasMoreSignatures = false;
                        }
                        hasMoreSignatures = Boolean(hasMoreSignatures && currentOptions.limit && signatures.length === currentOptions.limit);
                        return [3, 1];
                    case 3:
                        filteredSignatures = allSignatures.filter(function (signatureTransaction) {
                            if (fromSlot && signatureTransaction.slot < fromSlot)
                                return false;
                            if (toSlot && signatureTransaction.slot > toSlot)
                                return false;
                            return true;
                        });
                        return [4, Promise.all(filteredSignatures.map(function (signatureTransaction) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
                                var events;
                                return tslib_1.__generator(this, function (_a) {
                                    switch (_a.label) {
                                        case 0: return [4, this.readEventsFromSignature(signatureTransaction.signature, options.commitment)];
                                        case 1:
                                            events = _a.sent();
                                            return [2, events.map(function (event) { return (tslib_1.__assign(tslib_1.__assign({}, event), { confirmationStatus: signatureTransaction.confirmationStatus, blockTime: signatureTransaction.blockTime, signature: signatureTransaction.signature, slot: signatureTransaction.slot })); })];
                                    }
                                });
                            }); }))];
                    case 4:
                        eventsWithSlots = _a.sent();
                        return [2, eventsWithSlots.flat()];
                }
            });
        });
    };
    SvmCpiEventsClient.prototype.readEventsFromSignature = function (txSignature, commitment) {
        if (commitment === void 0) { commitment = "confirmed"; }
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var txResult;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, this.rpc
                            .getTransaction(txSignature, { commitment: commitment, maxSupportedTransactionVersion: 0 })
                            .send()];
                    case 1:
                        txResult = _a.sent();
                        if (txResult === null)
                            return [2, []];
                        return [2, this.processEventFromTx(txResult)];
                }
            });
        });
    };
    SvmCpiEventsClient.prototype.processEventFromTx = function (txResult) {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        if (!txResult)
            return [];
        var events = [];
        var accountKeys = txResult.transaction.message.accountKeys;
        var messageAccountKeys = tslib_1.__spreadArray([], accountKeys, true);
        messageAccountKeys.push.apply(messageAccountKeys, ((_c = (_b = (_a = txResult === null || txResult === void 0 ? void 0 : txResult.meta) === null || _a === void 0 ? void 0 : _a.loadedAddresses) === null || _b === void 0 ? void 0 : _b.writable) !== null && _c !== void 0 ? _c : []));
        messageAccountKeys.push.apply(messageAccountKeys, ((_f = (_e = (_d = txResult === null || txResult === void 0 ? void 0 : txResult.meta) === null || _d === void 0 ? void 0 : _d.loadedAddresses) === null || _e === void 0 ? void 0 : _e.readonly) !== null && _f !== void 0 ? _f : []));
        for (var _i = 0, _j = (_h = (_g = txResult.meta) === null || _g === void 0 ? void 0 : _g.innerInstructions) !== null && _h !== void 0 ? _h : []; _i < _j.length; _i++) {
            var ixBlock = _j[_i];
            for (var _k = 0, _l = ixBlock.instructions; _k < _l.length; _k++) {
                var ix = _l[_k];
                var ixProgramId = messageAccountKeys[ix.programIdIndex];
                var singleIxAccount = ix.accounts.length === 1 ? messageAccountKeys[ix.accounts[0]] : undefined;
                if (ixProgramId !== undefined &&
                    singleIxAccount !== undefined &&
                    this.programAddress === ixProgramId &&
                    this.programEventAuthority === singleIxAccount) {
                    var ixData = utils_1.bs58.decode(ix.data);
                    var eventData = Buffer.from(ixData.slice(8)).toString("base64");
                    var _m = (0, utils_2.decodeEvent)(this.idl, eventData), name_1 = _m.name, data = _m.data;
                    events.push({ program: this.programAddress, name: name_1, data: data });
                }
            }
        }
        return events;
    };
    SvmCpiEventsClient.prototype.getDepositEventsFromSignature = function (originChainId, txSignature, commitment) {
        if (commitment === void 0) { commitment = "confirmed"; }
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _a, events, txDetails, depositEvents;
            return tslib_1.__generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        (0, assert_1.default)((0, utils_1.chainIsSvm)(originChainId), "Origin chain ".concat(originChainId, " is not an SVM chain"));
                        return [4, Promise.all([
                                this.readEventsFromSignature(txSignature, commitment),
                                this.rpc
                                    .getTransaction(txSignature, {
                                    commitment: commitment,
                                    maxSupportedTransactionVersion: 0,
                                })
                                    .send(),
                            ])];
                    case 1:
                        _a = _b.sent(), events = _a[0], txDetails = _a[1];
                        depositEvents = events === null || events === void 0 ? void 0 : events.filter(function (event) { return (event === null || event === void 0 ? void 0 : event.name) === "FundsDeposited"; });
                        if (!txDetails || !(depositEvents === null || depositEvents === void 0 ? void 0 : depositEvents.length)) {
                            return [2];
                        }
                        return [2, events.map(function (event) {
                                var unwrappedEventArgs = (0, _1.unwrapEventData)(event, [
                                    "depositId",
                                    "outputAmount",
                                ]);
                                var data = unwrappedEventArgs.data;
                                return tslib_1.__assign(tslib_1.__assign({}, data), { depositor: (0, utils_1.toAddressType)(data.depositor, data.originChainId), recipient: (0, utils_1.toAddressType)(data.recipient, data.destinationChainId), exclusiveRelayer: (0, utils_1.toAddressType)(data.exclusiveRelayer, data.destinationChainId), inputToken: (0, utils_1.toAddressType)(data.inputToken, data.originChainId), outputToken: (0, utils_1.toAddressType)(data.outputToken, data.destinationChainId), depositTimestamp: Number(txDetails.blockTime), originChainId: originChainId, messageHash: (0, utils_1.getMessageHash)(data.message), blockNumber: Number(txDetails.slot), txnIndex: 0, txnRef: txSignature, logIndex: 0 });
                            })];
                }
            });
        });
    };
    SvmCpiEventsClient.prototype.getFillEventsFromSignature = function (destinationChainId, txSignature, commitment) {
        if (commitment === void 0) { commitment = "confirmed"; }
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _a, events, txDetails, fillEvents;
            return tslib_1.__generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        (0, assert_1.default)((0, utils_1.chainIsSvm)(destinationChainId), "Destination chain ".concat(destinationChainId, " is not an SVM chain"));
                        return [4, Promise.all([
                                this.readEventsFromSignature(txSignature, commitment),
                                this.rpc
                                    .getTransaction(txSignature, {
                                    commitment: commitment,
                                    maxSupportedTransactionVersion: 0,
                                })
                                    .send(),
                            ])];
                    case 1:
                        _a = _b.sent(), events = _a[0], txDetails = _a[1];
                        fillEvents = events === null || events === void 0 ? void 0 : events.filter(function (event) { return (event === null || event === void 0 ? void 0 : event.name) === "FilledRelay"; });
                        if (!txDetails || !(fillEvents === null || fillEvents === void 0 ? void 0 : fillEvents.length)) {
                            return [2];
                        }
                        return [2, fillEvents.map(function (event) {
                                var unwrappedEventData = (0, _1.unwrapEventData)(event, [
                                    "depositId",
                                    "inputAmount",
                                ]);
                                var data = unwrappedEventData.data;
                                return tslib_1.__assign(tslib_1.__assign({}, data), { depositor: (0, utils_1.toAddressType)(data.depositor, data.originChainId), recipient: (0, utils_1.toAddressType)(data.recipient, data.destinationChainId), exclusiveRelayer: (0, utils_1.toAddressType)(data.exclusiveRelayer, data.destinationChainId), inputToken: (0, utils_1.toAddressType)(data.inputToken, data.originChainId), outputToken: (0, utils_1.toAddressType)(data.outputToken, data.destinationChainId), fillTimestamp: Number(txDetails.blockTime), blockNumber: Number(txDetails.slot), txnRef: txSignature, txnIndex: 0, logIndex: 0, destinationChainId: destinationChainId });
                            })];
                }
            });
        });
    };
    SvmCpiEventsClient.prototype.getProgramAddress = function () {
        return this.programAddress;
    };
    SvmCpiEventsClient.prototype.getRpc = function () {
        return this.rpc;
    };
    return SvmCpiEventsClient;
}());
exports.SvmCpiEventsClient = SvmCpiEventsClient;
//# sourceMappingURL=eventsClient.js.map