"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UniswapV2PoolSubgraphTemplateTokenFetcher = void 0;
const dataloader_1 = __importDefault(require("dataloader"));
const lodash_1 = require("lodash");
const blocks_1 = require("../../../app-toolkit/constants/blocks");
const the_graph_helper_1 = require("../../../app-toolkit/helpers/the-graph.helper");
const uniswap_v2_pool_on_chain_template_token_fetcher_1 = require("./uniswap-v2.pool.on-chain.template.token-fetcher");
const uniswap_v2_pool_subgraph_types_1 = require("./uniswap-v2.pool.subgraph.types");
class UniswapV2PoolSubgraphTemplateTokenFetcher extends uniswap_v2_pool_on_chain_template_token_fetcher_1.UniswapV2PoolOnChainTemplateTokenFetcher {
    constructor() {
        super(...arguments);
        this.first = 1000;
        this.orderBy = 'reserveUSD';
        this.poolsQuery = uniswap_v2_pool_subgraph_types_1.DEFAULT_POOLS_QUERY;
        this.poolsByIdQuery = uniswap_v2_pool_subgraph_types_1.DEFAULT_POOLS_BY_ID_QUERY;
        this.requiredPools = [];
        this.ignoredPools = [];
        this.skipVolume = false;
        this.lastBlockSyncedOnGraphQuery = uniswap_v2_pool_subgraph_types_1.DEFAULT_LAST_BLOCK_SYNCED_ON_GRAPH_QUERY;
        this.poolVolumesByIdQuery = uniswap_v2_pool_subgraph_types_1.DEFAULT_POOL_VOLUMES_BY_ID_QUERY;
        this.poolVolumesByIdAtBlockQuery = uniswap_v2_pool_subgraph_types_1.DEFAULT_POOL_VOLUMES_BY_ID_AT_BLOCK_QUERY;
    }
    getAddresses() {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const dataLoaderOptions = { cache: true, maxBatchSize: 1000 };
            if (!this.skipVolume) {
                this.volumeDataLoader = new dataloader_1.default(this.batchGetVolume.bind(this), dataLoaderOptions);
            }
            const chunks = yield Promise.all((0, lodash_1.range)(0, this.first, 1000).map(skip => {
                const count = Math.min(1000, this.first - skip);
                return (0, the_graph_helper_1.gqlFetch)({
                    endpoint: this.subgraphUrl,
                    query: this.poolsQuery,
                    variables: { first: count, skip, orderBy: this.orderBy },
                });
            }));
            const poolsData = chunks.flat();
            const poolsByIdData = yield (0, the_graph_helper_1.gqlFetch)({
                endpoint: this.subgraphUrl,
                query: this.poolsByIdQuery,
                variables: { ids: this.requiredPools },
            });
            const pools = poolsData.map(v => { var _a; return (_a = v.pairs) !== null && _a !== void 0 ? _a : []; }).flat();
            const poolsById = (_a = poolsByIdData.pairs) !== null && _a !== void 0 ? _a : [];
            const poolIds = [...pools, ...poolsById].map(v => v.id.toLowerCase());
            const uniquePoolIds = (0, lodash_1.uniq)(poolIds);
            const filteredPoolIds = (0, lodash_1.difference)(uniquePoolIds, this.ignoredPools);
            return filteredPoolIds;
        });
    }
    getPoolFactoryContract(_address) {
        throw new Error('Method not implemented.');
    }
    getPoolsLength(_contract) {
        throw new Error('Method not implemented.');
    }
    getPoolAddress(_contract, _index) {
        throw new Error('Method not implemented.');
    }
    getApy({ appToken }) {
        return __awaiter(this, void 0, void 0, function* () {
            const liquidity = appToken.supply * appToken.price;
            const volume = this.volumeDataLoader ? yield this.volumeDataLoader.load(appToken.address) : 0;
            const yearlyFees = volume * (this.fee / 100) * 365;
            const apy = yearlyFees / liquidity;
            return apy * 100;
        });
    }
    getDataProps(params) {
        const _super = Object.create(null, {
            getDataProps: { get: () => super.getDataProps }
        });
        return __awaiter(this, void 0, void 0, function* () {
            const defaultDataProps = yield _super.getDataProps.call(this, params);
            const volume = this.volumeDataLoader ? yield this.volumeDataLoader.load(params.appToken.address) : 0;
            return Object.assign(Object.assign({}, defaultDataProps), { volume });
        });
    }
    batchGetVolume(addresses) {
        return __awaiter(this, void 0, void 0, function* () {
            const provider = this.appToolkit.getNetworkProvider(this.network);
            const block = yield provider.getBlockNumber();
            const block1DayAgo = block - blocks_1.BLOCKS_PER_DAY[this.network];
            let blockNumberLastSynced = 0;
            if (this.subgraphUrl.includes('api.fura.org')) {
                const subgraphName = this.subgraphUrl.substring(this.subgraphUrl.lastIndexOf('/') + 1);
                const graphMetaData = yield (0, the_graph_helper_1.gqlFetch)({
                    endpoint: this.subgraphUrl,
                    query: uniswap_v2_pool_subgraph_types_1.FURA_LAST_BLOCK_SYNCED_ON_GRAPH_QUERY,
                    variables: { subgraphName },
                });
                blockNumberLastSynced = graphMetaData.indexingStatusForCurrentVersion.chains[0].latestBlock.number;
            }
            else {
                const graphMetaData = yield (0, the_graph_helper_1.gqlFetch)({
                    endpoint: this.subgraphUrl,
                    query: this.lastBlockSyncedOnGraphQuery,
                });
                blockNumberLastSynced = graphMetaData._meta.block.number;
            }
            if (block1DayAgo > blockNumberLastSynced)
                return addresses.map(() => 0);
            const [volumeByIDData, volumeByIDData1DayAgo] = yield Promise.all([
                (0, the_graph_helper_1.gqlFetch)({
                    endpoint: this.subgraphUrl,
                    query: this.poolVolumesByIdQuery,
                    variables: { ids: addresses },
                }),
                (0, the_graph_helper_1.gqlFetch)({
                    endpoint: this.subgraphUrl,
                    query: this.poolVolumesByIdAtBlockQuery,
                    variables: { ids: addresses, block: block1DayAgo },
                }),
            ]);
            const poolVolumes = addresses.map((address) => __awaiter(this, void 0, void 0, function* () {
                const pairVolumeToday = volumeByIDData.pairs.find(p => p.id === address);
                const poolVolumeYesterday = volumeByIDData1DayAgo.pairs.find(p => p.id === address);
                let volume;
                if ((pairVolumeToday === null || pairVolumeToday === void 0 ? void 0 : pairVolumeToday.volumeUSD) && (poolVolumeYesterday === null || poolVolumeYesterday === void 0 ? void 0 : poolVolumeYesterday.volumeUSD)) {
                    const volumeUSDToday = Number(pairVolumeToday.volumeUSD);
                    const volumeUSDYesterday = Number(poolVolumeYesterday.volumeUSD);
                    volume = volumeUSDToday - volumeUSDYesterday;
                }
                else if ((pairVolumeToday === null || pairVolumeToday === void 0 ? void 0 : pairVolumeToday.untrackedVolumeUSD) && (poolVolumeYesterday === null || poolVolumeYesterday === void 0 ? void 0 : poolVolumeYesterday.untrackedVolumeUSD)) {
                    const volumeUSDToday = Number(pairVolumeToday.untrackedVolumeUSD);
                    const volumeUSDYesterday = Number(poolVolumeYesterday.untrackedVolumeUSD);
                    volume = volumeUSDToday - volumeUSDYesterday;
                }
                else {
                    volume = 0;
                }
                return volume;
            }));
            return poolVolumes;
        });
    }
}
exports.UniswapV2PoolSubgraphTemplateTokenFetcher = UniswapV2PoolSubgraphTemplateTokenFetcher;
//# sourceMappingURL=uniswap-v2.pool.subgraph.template.token-fetcher.js.map