"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CachedSolanaRpcFactory = void 0;
var tslib_1 = require("tslib");
var rpc_transformers_1 = require("@solana/rpc-transformers");
var superstruct_1 = require("superstruct");
var baseRpcFactories_1 = require("./baseRpcFactories");
var utils_1 = require("../utils");
var utils_2 = require("../../utils");
var retryRpcFactory_1 = require("./retryRpcFactory");
var CachedSolanaRpcFactory = (function (_super) {
    tslib_1.__extends(CachedSolanaRpcFactory, _super);
    function CachedSolanaRpcFactory(providerCacheNamespace, redisClient) {
        var _this = this;
        var retryConstructorParams = [];
        for (var _i = 2; _i < arguments.length; _i++) {
            retryConstructorParams[_i - 2] = arguments[_i];
        }
        var superParams = retryConstructorParams.slice(-2);
        _this = _super.apply(this, superParams) || this;
        _this.redisClient = redisClient;
        var retryRpcFactory = new (retryRpcFactory_1.RetrySolanaRpcFactory.bind.apply(retryRpcFactory_1.RetrySolanaRpcFactory, tslib_1.__spreadArray([void 0], retryConstructorParams, false)))();
        _this.retryTransport = retryRpcFactory.createTransport();
        _this.retryRpcClient = retryRpcFactory.createRpcClient();
        var cachePrefix = "".concat(providerCacheNamespace, ",").concat(new URL(_this.clusterUrl).hostname, ",").concat(_this.chainId);
        _this.getTransactionCachePrefix = "".concat(cachePrefix, ":getTransaction,");
        return _this;
    }
    CachedSolanaRpcFactory.prototype.createTransport = function () {
        var _this = this;
        return function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            return tslib_1.__awaiter(_this, void 0, void 0, function () {
                var _a, method, params, cacheType, redisKey, redisResult;
                var _b;
                return tslib_1.__generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            _a = args[0].payload, method = _a.method, params = _a.params;
                            cacheType = this.redisClient ? this.cacheType(method) : utils_1.CacheType.NONE;
                            if (cacheType === utils_1.CacheType.NONE) {
                                return [2, this.retryTransport.apply(this, args)];
                            }
                            redisKey = this.buildRedisKey(method, params);
                            return [4, ((_b = this.redisClient) === null || _b === void 0 ? void 0 : _b.get(redisKey))];
                        case 1:
                            redisResult = _c.sent();
                            if (redisResult) {
                                return [2, JSON.parse(redisResult, utils_2.jsonReviverWithBigInts)];
                            }
                            return [2, this.requestAndCacheFinalized.apply(this, args)];
                    }
                });
            });
        };
    };
    CachedSolanaRpcFactory.prototype.requestAndCacheFinalized = function () {
        var _a, _b;
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _c, method, params, getSignatureStatusesResponse, error_1, getTransactionResponse, redisKey;
            return tslib_1.__generator(this, function (_d) {
                switch (_d.label) {
                    case 0:
                        _c = args[0].payload, method = _c.method, params = _c.params;
                        if (method !== "getTransaction")
                            return [2, this.retryTransport.apply(this, args)];
                        if (!this.isGetTransactionParams(params))
                            return [2, this.retryTransport.apply(this, args)];
                        _d.label = 1;
                    case 1:
                        _d.trys.push([1, 3, , 4]);
                        return [4, this.retryRpcClient
                                .getSignatureStatuses([params[0]], {
                                searchTransactionHistory: true,
                            })
                                .send()];
                    case 2:
                        getSignatureStatusesResponse = _d.sent();
                        if (((_a = getSignatureStatusesResponse.value[0]) === null || _a === void 0 ? void 0 : _a.confirmationStatus) !== "finalized") {
                            return [2, this.retryTransport.apply(this, args)];
                        }
                        return [3, 4];
                    case 3:
                        error_1 = _d.sent();
                        return [2, this.retryTransport.apply(this, args)];
                    case 4: return [4, this.retryTransport.apply(this, args)];
                    case 5:
                        getTransactionResponse = _d.sent();
                        try {
                            (0, rpc_transformers_1.getThrowSolanaErrorResponseTransformer)()(getTransactionResponse, { methodName: method, params: params });
                        }
                        catch (_e) {
                            return [2, getTransactionResponse];
                        }
                        redisKey = this.buildRedisKey(method, params);
                        return [4, ((_b = this.redisClient) === null || _b === void 0 ? void 0 : _b.set(redisKey, JSON.stringify(getTransactionResponse, utils_2.jsonReplacerWithBigInts), Number.POSITIVE_INFINITY))];
                    case 6:
                        _d.sent();
                        return [2, getTransactionResponse];
                }
            });
        });
    };
    CachedSolanaRpcFactory.prototype.buildRedisKey = function (method, params) {
        switch (method) {
            case "getTransaction":
                return this.getTransactionCachePrefix + JSON.stringify(params, utils_2.jsonReplacerWithBigInts);
            default:
                throw new Error("CachedSolanaRpcFactory::buildRedisKey: invalid JSON-RPC method ".concat(method));
        }
    };
    CachedSolanaRpcFactory.prototype.cacheType = function (method) {
        if (method === "getTransaction") {
            return utils_1.CacheType.NO_TTL;
        }
        else {
            return utils_1.CacheType.NONE;
        }
    };
    CachedSolanaRpcFactory.prototype.isGetTransactionParams = function (params) {
        return (0, superstruct_1.is)(params, (0, superstruct_1.tuple)([
            (0, superstruct_1.string)(),
            (0, superstruct_1.optional)((0, superstruct_1.object)()),
        ]));
    };
    return CachedSolanaRpcFactory;
}(baseRpcFactories_1.SolanaClusterRpcFactory));
exports.CachedSolanaRpcFactory = CachedSolanaRpcFactory;
//# sourceMappingURL=cachedRpcFactory.js.map