"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RouteResolver = void 0;
const sdk_definitions_1 = require("@wormhole-foundation/sdk-definitions");
const route_1 = require("./route");
const token_1 = require("./token");
class RouteResolver {
    wh;
    routeConstructors;
    inputTokenList;
    constructor(wh, routeConstructors) {
        this.wh = wh;
        this.routeConstructors = routeConstructors;
    }
    async supportedSourceTokens(chain) {
        if (this.inputTokenList)
            return this.inputTokenList;
        const itl = await Promise.all(this.routeConstructors.map(async (rc) => rc.supportedSourceTokens(chain)));
        this.inputTokenList = (0, token_1.uniqueTokens)(itl.flat());
        return this.inputTokenList;
    }
    async supportedDestinationTokens(inputToken, fromChain, toChain) {
        const [, inputTokenId] = (0, sdk_definitions_1.resolveWrappedToken)(fromChain.network, fromChain.chain, inputToken);
        const tokens = await Promise.all(this.routeConstructors.map(async (rc) => rc.supportedDestinationTokens(inputTokenId, fromChain, toChain)));
        return (0, token_1.uniqueTokens)(tokens.flat());
    }
    async findRoutes(request) {
        // First we find all routes which support the request inputs (network, chains, and tokens)
        const supportedRoutes = await Promise.all(this.routeConstructors.map(async (rc) => {
            let protocolSupported = rc.supportedNetworks().includes(this.wh.network) &&
                rc.supportedChains(this.wh.network).includes(request.to.chain) &&
                rc.supportedChains(this.wh.network).includes(request.from.chain) &&
                rc.isProtocolSupported(request.fromChain) &&
                rc.isProtocolSupported(request.toChain);
            let sourceTokenSupported = (await rc.supportedSourceTokens(request.fromChain)).filter((tokenId) => {
                return tokenId.address.toString() === request.source.id.address.toString();
            }).length > 0;
            let destinationTokenSupported = (await rc.supportedDestinationTokens(request.source.id, request.fromChain, request.toChain)).filter((tokenId) => {
                return tokenId.address.toString() === request.destination.id.address.toString();
            }).length > 0;
            return protocolSupported && sourceTokenSupported && destinationTokenSupported;
        })).then((routesSupported) => this.routeConstructors.filter((_, index) => routesSupported[index]));
        // Next, we make sure all supported routes are available. For relayed routes, this will ping
        // the relayer to make sure it's online.
        return await Promise.all(supportedRoutes.map(async (rc) => {
            const route = new rc(this.wh, request);
            const available = (0, route_1.isAutomatic)(route) ? await route.isAvailable() : true;
            return [route, available];
        }))
            .then((availableRoutes) => availableRoutes.filter(([_, available]) => available))
            .then((availableRoutes) => availableRoutes.map(([route, _]) => route));
    }
    async sortRoutes(routes, sortBy) {
        // TODO: actually sort
        return routes;
    }
}
exports.RouteResolver = RouteResolver;
//# sourceMappingURL=resolver.js.map