import * as __typia_transform__assertGuard from "typia/lib/internal/_assertGuard.js";
import * as __typia_transform__accessExpressionAsString from "typia/lib/internal/_accessExpressionAsString.js";
import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';
import { getDefaultResolver } from '../../config.js';
import Resolver from '../../lib/resolver.js';
import { createAssertEquals } from 'typia';
import { KeetaAnchorError, KeetaAnchorUserValidationError } from '../../lib/error.js';
import { SignData } from '../../lib/utils/signing.js';
import { isKeetaUsernameAnchorResolveResponseJSON, isKeetaUsernameAnchorClaimResponseJSON, parseGloballyIdentifiableUsername, getUsernameClaimSignable, validateUsernameDefault, isGloballyIdentifiableUsername, isKeetaNetPublicKeyString, Errors, getUsernameTransferSignable, getUsernameReleaseSignable, isKeetaUsernameAnchorReleaseResponseJSON, formatGloballyIdentifiableUsername, isKeetaUsernameAnchorSearchResponseJSON } from './common.js';
import { assertNever } from '../../lib/utils/never.js';
const KeetaUsernameAnchorClientAccessToken = Symbol('KeetaUsernameAnchorClientAccessToken');
const assertServiceMetadataEndpoint = (() => { const _io0 = (input, _exceptionable = true) => "string" === typeof input.url && (undefined === input.options || "object" === typeof input.options && null !== input.options && false === Array.isArray(input.options) && _io1(input.options, true && _exceptionable)) && (1 === Object.keys(input).length || Object.keys(input).every(key => {
    if (["url", "options"].some(prop => key === prop))
        return true;
    const value = input[key];
    if (undefined === value)
        return true;
    return false;
})); const _io1 = (input, _exceptionable = true) => (undefined === input.authentication || "object" === typeof input.authentication && null !== input.authentication && _io2(input.authentication, true && _exceptionable)) && (0 === Object.keys(input).length || Object.keys(input).every(key => {
    if (["authentication"].some(prop => key === prop))
        return true;
    const value = input[key];
    if (undefined === value)
        return true;
    return false;
})); const _io2 = (input, _exceptionable = true) => "keeta-account" === input.method && ("optional" === input.type || "required" === input.type || "none" === input.type) && (2 === Object.keys(input).length || Object.keys(input).every(key => {
    if (["method", "type"].some(prop => key === prop))
        return true;
    const value = input[key];
    if (undefined === value)
        return true;
    return false;
})); const _ao0 = (input, _path, _exceptionable = true) => ("string" === typeof input.url || __typia_transform__assertGuard._assertGuard(_exceptionable, {
    method: "createAssertEquals",
    path: _path + ".url",
    expected: "string",
    value: input.url
}, _errorFactory)) && (undefined === input.options || ("object" === typeof input.options && null !== input.options && false === Array.isArray(input.options) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
    method: "createAssertEquals",
    path: _path + ".options",
    expected: "(__type.o1 | undefined)",
    value: input.options
}, _errorFactory)) && _ao1(input.options, _path + ".options", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
    method: "createAssertEquals",
    path: _path + ".options",
    expected: "(__type.o1 | undefined)",
    value: input.options
}, _errorFactory)) && (1 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
    if (["url", "options"].some(prop => key === prop))
        return true;
    const value = input[key];
    if (undefined === value)
        return true;
    return __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "createAssertEquals",
        path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
        expected: "undefined",
        value: value
    }, _errorFactory);
}))); const _ao1 = (input, _path, _exceptionable = true) => (undefined === input.authentication || ("object" === typeof input.authentication && null !== input.authentication || __typia_transform__assertGuard._assertGuard(_exceptionable, {
    method: "createAssertEquals",
    path: _path + ".authentication",
    expected: "(ServiceMetadataAuthenticationType | undefined)",
    value: input.authentication
}, _errorFactory)) && _ao2(input.authentication, _path + ".authentication", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
    method: "createAssertEquals",
    path: _path + ".authentication",
    expected: "(ServiceMetadataAuthenticationType | undefined)",
    value: input.authentication
}, _errorFactory)) && (0 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
    if (["authentication"].some(prop => key === prop))
        return true;
    const value = input[key];
    if (undefined === value)
        return true;
    return __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "createAssertEquals",
        path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
        expected: "undefined",
        value: value
    }, _errorFactory);
}))); const _ao2 = (input, _path, _exceptionable = true) => ("keeta-account" === input.method || __typia_transform__assertGuard._assertGuard(_exceptionable, {
    method: "createAssertEquals",
    path: _path + ".method",
    expected: "\"keeta-account\"",
    value: input.method
}, _errorFactory)) && ("optional" === input.type || "required" === input.type || "none" === input.type || __typia_transform__assertGuard._assertGuard(_exceptionable, {
    method: "createAssertEquals",
    path: _path + ".type",
    expected: "(\"none\" | \"optional\" | \"required\")",
    value: input.type
}, _errorFactory)) && (2 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
    if (["method", "type"].some(prop => key === prop))
        return true;
    const value = input[key];
    if (undefined === value)
        return true;
    return __typia_transform__assertGuard._assertGuard(_exceptionable, {
        method: "createAssertEquals",
        path: _path + __typia_transform__accessExpressionAsString._accessExpressionAsString(key),
        expected: "undefined",
        value: value
    }, _errorFactory);
}))); const __is = (input, _exceptionable = true) => null !== input && undefined !== input && ("string" === typeof input || "object" === typeof input && null !== input && _io0(input, true)); let _errorFactory; return (input, errorFactory) => {
    if (false === __is(input)) {
        _errorFactory = errorFactory;
        ((input, _path, _exceptionable = true) => (null !== input || __typia_transform__assertGuard._assertGuard(true, {
            method: "createAssertEquals",
            path: _path + "",
            expected: "(__type | string)",
            value: input
        }, _errorFactory)) && (undefined !== input || __typia_transform__assertGuard._assertGuard(true, {
            method: "createAssertEquals",
            path: _path + "",
            expected: "(__type | string)",
            value: input
        }, _errorFactory)) && ("string" === typeof input || ("object" === typeof input && null !== input || __typia_transform__assertGuard._assertGuard(true, {
            method: "createAssertEquals",
            path: _path + "",
            expected: "(__type | string)",
            value: input
        }, _errorFactory)) && _ao0(input, _path + "", true) || __typia_transform__assertGuard._assertGuard(true, {
            method: "createAssertEquals",
            path: _path + "",
            expected: "(__type | string)",
            value: input
        }, _errorFactory)))(input, "$input", true);
    }
    return input;
}; })();
function typedUsernameServiceEntries(obj) {
    // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
    return Object.entries(obj);
}
function validateURL(url) {
    if (!url) {
        throw (new Error('Invalid URL: empty value'));
    }
    return (new URL(url));
}
async function getEndpoints(resolver, criteria, shared, logger) {
    const response = await resolver.lookup('username', criteria, shared);
    if (response === undefined) {
        return (null);
    }
    const serviceInfoPromises = Object.entries(response).map(async function ([id, serviceInfo]) {
        const operations = await serviceInfo.operations('object');
        const operationsFunctions = {};
        for (const [key, operation] of Object.entries(operations)) {
            if (operation === undefined) {
                continue;
            }
            Object.defineProperty(operationsFunctions, key, {
                get: async function () {
                    const endpoint = assertServiceMetadataEndpoint(await Resolver.Metadata.fullyResolveValuizable(operation));
                    let url;
                    let authentication = {
                        method: 'keeta-account',
                        type: 'none'
                    };
                    if (typeof endpoint === 'string') {
                        url = endpoint;
                    }
                    else {
                        url = endpoint.url;
                        if (endpoint.options?.authentication) {
                            authentication = endpoint.options.authentication;
                        }
                    }
                    return ({
                        url: function (params) {
                            let substitutedURL;
                            try {
                                substitutedURL = decodeURI(url);
                            }
                            catch (error) {
                                logger?.debug('UsernameAnchor:getEndpoints', 'Failed to decode URI, using original URL for substitution', error, url);
                                substitutedURL = url;
                            }
                            for (const [paramKey, paramValue] of Object.entries(params ?? {})) {
                                substitutedURL = substitutedURL.replace(`{${paramKey}}`, encodeURIComponent(paramValue));
                            }
                            return (validateURL(substitutedURL));
                        },
                        options: { authentication }
                    });
                },
                enumerable: true,
                configurable: true
            });
        }
        if (!Object.prototype.hasOwnProperty.call(operationsFunctions, 'resolve')) {
            throw (new Error('Username service is missing resolve operation'));
        }
        return ([
            // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
            id,
            {
                operations: operationsFunctions,
                ...(await (async () => {
                    const pattern = await serviceInfo.usernamePattern?.('string');
                    if (pattern !== undefined) {
                        return ({ usernamePattern: pattern });
                    }
                    return ({});
                })())
            }
        ]);
    });
    if (serviceInfoPromises.length === 0) {
        return (null);
    }
    const entries = await Promise.all(serviceInfoPromises);
    // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
    return Object.fromEntries(entries);
}
class KeetaUsernameAnchorBase {
    client;
    logger;
    account;
    signer;
    constructor(config) {
        this.client = config.client;
        this.logger = config.logger;
        this.account = config.account;
        this.signer = config.signer;
    }
}
class KeetaUsernameAnchorProvider extends KeetaUsernameAnchorBase {
    serviceInfo;
    providerID;
    #usernamePattern;
    parent;
    constructor(serviceInfo, providerID, parent) {
        const parentInternals = parent._internals(KeetaUsernameAnchorClientAccessToken);
        super(parentInternals);
        this.serviceInfo = serviceInfo;
        this.providerID = providerID;
        this.parent = parent;
        if (serviceInfo.usernamePattern !== undefined) {
            try {
                this.#usernamePattern = new RegExp(serviceInfo.usernamePattern);
            }
            catch (error) {
                throw (new Error(`Invalid usernamePattern metadata for provider ${String(providerID)}: ${error instanceof Error ? error.message : String(error)}`));
            }
        }
    }
    get usernamePattern() {
        return (this.#usernamePattern?.source);
    }
    /**
     * Check if a username is valid according to the provider's username pattern if set and default validation.
     * @param username The username to check
     * @returns True if the username is valid, false otherwise
     */
    isUsernameValid(username) {
        try {
            validateUsernameDefault(username, {
                pattern: this.#usernamePattern,
                fieldPath: 'username'
            });
            return (true);
        }
        catch (error) {
            if (error instanceof KeetaAnchorUserValidationError) {
                return (false);
            }
            throw (error);
        }
    }
    #assertProviderIssuedNameValid(username) {
        validateUsernameDefault(username, {
            pattern: this.#usernamePattern,
            fieldPath: 'username'
        });
    }
    async #getOperation(operationName) {
        const operationGetter = this.serviceInfo.operations[operationName];
        if (operationGetter === undefined) {
            throw (new Error(`Username provider does not support ${operationName} operation`));
        }
        const endpoint = await operationGetter;
        if (endpoint === undefined) {
            throw (new Error(`Username provider does not support ${operationName} operation`));
        }
        if (endpoint.options.authentication.method !== 'keeta-account') {
            throw (new Error(`Unsupported authentication method: ${endpoint.options.authentication.method}`));
        }
        return (endpoint);
    }
    async #parseResponseError(data) {
        try {
            return (await KeetaAnchorError.fromJSON(data));
        }
        catch (error) {
            this.logger?.debug('UsernameAnchor', 'Failed to parse error response', error, data);
            if (typeof data === 'object' && data !== null && 'error' in data && typeof data.error === 'string') {
                return (new Error(data.error));
            }
            return (new Error('Username provider request failed'));
        }
    }
    #toKeetaUsernameAnchorUsernameWithAccountAndProvider(response) {
        return ({
            account: KeetaNetLib.Account.toAccount(response.account),
            username: response.username,
            providerID: this.providerID,
            globallyIdentifiableUsername: formatGloballyIdentifiableUsername(response.username, String(this.providerID))
        });
    }
    /**
     * Resolve a username for a specific provider
     * @param input The value to lookup, can be a username, PublicKeyString, or an account
     * @returns The resolved account and username, or null if not found
     */
    async resolve(input) {
        let toResolveString;
        if (typeof input === 'string') {
            toResolveString = input;
        }
        else {
            toResolveString = input.publicKeyString.get();
        }
        if (!(isKeetaNetPublicKeyString(toResolveString))) {
            this.#assertProviderIssuedNameValid(toResolveString);
        }
        const endpoint = await this.#getOperation('resolve');
        if (endpoint.options.authentication.type === 'required') {
            throw (new Error('Username provider requires authentication which is not supported by the client'));
        }
        const serviceURL = endpoint.url({ toResolve: toResolveString });
        const response = await fetch(serviceURL);
        let responseJSON;
        try {
            responseJSON = await response.json();
        }
        catch (error) {
            throw (new Error(`Failed to parse username provider response as JSON: ${error}`));
        }
        if (!isKeetaUsernameAnchorResolveResponseJSON(responseJSON)) {
            throw (new Error('Invalid response from username provider'));
        }
        if (!responseJSON.ok) {
            const responseError = await this.#parseResponseError(responseJSON);
            if (Errors.UserNotFound.isInstance(responseError)) {
                return (null);
            }
            throw (responseError);
        }
        const retval = this.#toKeetaUsernameAnchorUsernameWithAccountAndProvider(responseJSON);
        if (isKeetaNetPublicKeyString(toResolveString)) {
            if (!(retval.account.comparePublicKey(toResolveString))) {
                throw (new Error('Resolved account does not match the requested account'));
            }
        }
        else {
            if (retval.username !== toResolveString) {
                throw (new Error('Resolved username does not match the requested username'));
            }
        }
        return (retval);
    }
    /**
     * Claim a username for a specific provider
     * @param usernameInput The username to claim
     * @param options The account to claim for, and options related to transfer if applicable
     * @returns True if the claim was successful, false otherwise
     */
    async claimUsername(usernameInput, options) {
        let username;
        if (isGloballyIdentifiableUsername(usernameInput)) {
            const parsed = parseGloballyIdentifiableUsername(usernameInput);
            if (parsed.providerID !== String(this.providerID)) {
                throw (new Error(`Provider ID in username input does not match this provider's ID`));
            }
            username = parsed.username;
        }
        else {
            username = usernameInput;
        }
        this.#assertProviderIssuedNameValid(username);
        const endpoint = await this.#getOperation('claim');
        if (endpoint.options.authentication.type === 'none') {
            throw (new Error('Username claim operation must require account authentication'));
        }
        const accountToUse = options?.account ?? this.account ?? this.signer;
        if (!accountToUse) {
            throw (new Error('Account is required to claim a username'));
        }
        const request = {
            username,
            account: accountToUse
        };
        if (options?.transfer) {
            const from = KeetaNetLib.Account.toAccount(options.transfer.from);
            let signed = options.transfer.signed;
            if (!signed) {
                if (!from.hasPrivateKey) {
                    throw (new Error('Transfer "from" account must have a private key when signature is not provided'));
                }
                const signable = getUsernameTransferSignable({
                    username,
                    from: from,
                    to: accountToUse
                });
                signed = await SignData(from.assertAccount(), signable);
            }
            request.transfer = { from, signed };
        }
        const signed = await SignData(accountToUse.assertAccount(), getUsernameClaimSignable(request));
        const response = await fetch(endpoint.url(), {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            },
            body: JSON.stringify({
                username: username,
                account: accountToUse.publicKeyString.get(),
                transfer: request.transfer ? {
                    from: request.transfer.from.publicKeyString.get(),
                    signed: request.transfer.signed
                } : undefined,
                signed
            })
        });
        let responseJSON;
        try {
            responseJSON = await response.json();
        }
        catch (error) {
            throw (new Error(`Failed to parse username claim response as JSON: ${error}`));
        }
        if (!isKeetaUsernameAnchorClaimResponseJSON(responseJSON)) {
            throw (new Error('Invalid response from username provider claim endpoint'));
        }
        if (!responseJSON.ok) {
            throw (await this.#parseResponseError(responseJSON));
        }
        return (responseJSON.ok);
    }
    /**
     * Release a username for a specific provider
     * @param options The account to claim for, and options related to transfer if applicable
     * @returns True if the claim was successful, false otherwise
     */
    async releaseUsername(input) {
        const endpoint = await this.#getOperation('release');
        if (endpoint.options.authentication.type === 'none') {
            throw (new Error('Username claim operation must require account authentication'));
        }
        const accountToUse = input?.account ?? this.account ?? this.signer;
        if (!accountToUse) {
            throw (new Error('Account is required to claim a username'));
        }
        const signed = await SignData(accountToUse.assertAccount(), getUsernameReleaseSignable({ account: accountToUse }));
        const response = await fetch(endpoint.url(), {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            },
            body: JSON.stringify({
                account: accountToUse.publicKeyString.get(),
                signed
            })
        });
        let responseJSON;
        try {
            responseJSON = await response.json();
        }
        catch (error) {
            throw (new Error(`Failed to parse username claim response as JSON: ${error}`));
        }
        if (!isKeetaUsernameAnchorReleaseResponseJSON(responseJSON)) {
            throw (new Error('Invalid response from username provider claim endpoint'));
        }
        if (!responseJSON.ok) {
            throw (await this.#parseResponseError(responseJSON));
        }
        return (responseJSON.ok);
    }
    /**
     * Release a username for a specific provider
     * @param options The account to claim for, and options related to transfer if applicable
     * @returns True if the claim was successful, false otherwise
     */
    async search(parameters) {
        const endpoint = await this.#getOperation('search');
        if (endpoint.options.authentication.type !== 'none') {
            throw (new Error('Username search operation does not currently support authenticated endpoints'));
        }
        const urlWithParameters = (() => {
            const reconstructed = new URL(endpoint.url().toString());
            reconstructed.searchParams.set('search', parameters.search);
            return (reconstructed);
        })();
        const response = await fetch(urlWithParameters, {
            method: 'GET',
            headers: { 'Accept': 'application/json' }
        });
        let responseJSON;
        try {
            responseJSON = await response.json();
        }
        catch (error) {
            throw (new Error(`Failed to parse username claim response as JSON: ${error}`));
        }
        if (!isKeetaUsernameAnchorSearchResponseJSON(responseJSON)) {
            throw (new Error('Invalid response from username provider claim endpoint'));
        }
        if (!responseJSON.ok) {
            throw (await this.#parseResponseError(responseJSON));
        }
        const results = responseJSON.results.map((result) => {
            this.#assertProviderIssuedNameValid(result.username);
            return (this.#toKeetaUsernameAnchorUsernameWithAccountAndProvider(result));
        });
        return ({ results });
    }
}
class KeetaUsernameAnchorClient extends KeetaUsernameAnchorBase {
    resolver;
    id;
    constructor(client, config = {}) {
        super({ client, logger: config.logger, account: config.account, signer: config.signer });
        this.resolver = config.resolver ?? getDefaultResolver(client, config);
        this.id = config.id ?? crypto.randomUUID();
    }
    async #lookup(criteria = {}, shared) {
        const endpoints = await getEndpoints(this.resolver, criteria, shared, this.logger);
        if (endpoints === null) {
            return (null);
        }
        const providers = typedUsernameServiceEntries(endpoints).map(([providerID, serviceInfo]) => {
            return (new KeetaUsernameAnchorProvider(serviceInfo, providerID, this));
        });
        if (providers.length === 0) {
            return (null);
        }
        return (providers);
    }
    async getProvider(providerID, shared) {
        const mergedSharedCriteria = {
            ...shared,
            providerIDs: shared?.providerIDs !== undefined ? Array.from(new Set([...shared.providerIDs, providerID])) : [providerID]
        };
        const providers = await this.#lookup({}, mergedSharedCriteria);
        return (providers?.[0] ?? null);
    }
    async #requireProvider(providerID, shared) {
        const provider = await this.getProvider(providerID, shared);
        if (!provider) {
            throw (new Error(`Username provider ${providerID} not found`));
        }
        return (provider);
    }
    /**
     * Resolve a globally identifiable username via the appropriate provider.
     * @param username The globally identifiable username to resolve
     * @param shared Shared resolver lookup criteria
     * @returns The resolution result, or null if not found
     */
    async resolve(username, shared) {
        const { username: normalizedUsername, providerID } = parseGloballyIdentifiableUsername(username);
        const provider = await this.#requireProvider(providerID, shared);
        return (await provider.resolve(normalizedUsername));
    }
    /**
     * Resolve against all username providers for the given input.
     * @param input The value to search for, either a globally identifiable username, a username, or an account
     * @param shared Shared lookup criteria
     * @returns A mapping of provider IDs to their resolution results, or null if no providers found a match
     */
    // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
    async resolveMulti(input, shared) {
        if (isGloballyIdentifiableUsername(input)) {
            const { providerID } = parseGloballyIdentifiableUsername(input);
            const resolved = await this.resolve(input, shared);
            if (!resolved) {
                return (null);
            }
            return ({
                // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
                [providerID]: resolved
            });
        }
        const providers = await this.#lookup({}, shared);
        if (!providers) {
            return (null);
        }
        let foundOne = false;
        const response = {};
        await Promise.all(providers.map(async (provider) => {
            try {
                const result = await provider.resolve(input);
                if (result !== null) {
                    foundOne = true;
                    response[provider.providerID] = result;
                }
            }
            catch (error) {
                this.logger?.debug('UsernameAnchor:resolveMulti', `Error resolving username with provider ${String(provider.providerID)}`, error);
            }
        }));
        if (!foundOne) {
            return (null);
        }
        return (response);
    }
    async search(parameters, responseType = 'joined', shared) {
        const providers = await this.#lookup({}, shared);
        if (!providers) {
            return (null);
        }
        const response = {};
        await Promise.all(providers.map(async (provider) => {
            try {
                response[provider.providerID] = await provider.search(parameters);
            }
            catch (error) {
                this.logger?.debug('UsernameAnchor:search', `Error resolving username with provider ${String(provider.providerID)}`, error);
            }
        }));
        if (responseType === 'separate') {
            return (response);
        }
        else if (responseType === 'joined') {
            const joinedResults = [];
            for (const providerResponse of Object.values(response)) {
                // For some reason TypeScript loses the type information here, even though it is correctly inferred in the loop above. We have to manually assert the type to get the correct typings for results.
                // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
                const results = providerResponse.results;
                joinedResults.push(...results);
            }
            return ({ results: joinedResults });
        }
        else {
            assertNever(responseType);
        }
    }
    /**
     * Claim a globally identifiable username from the appropriate provider.
     * @param input The globally identifiable username to claim
     * @param options Claim options
     * @returns True if the claim was successful, false otherwise
     */
    async claimUsername(input, options, shared) {
        const { username, providerID } = parseGloballyIdentifiableUsername(input);
        const provider = await this.#requireProvider(providerID, shared);
        return (await provider.claimUsername(username, options));
    }
    async signUsernameTransfer(request, from) {
        const accountToUse = from ?? this.signer ?? this.account;
        if (!accountToUse) {
            throw (new Error('Signer or account is required to sign username transfer'));
        }
        const signable = getUsernameTransferSignable({
            ...request,
            from: accountToUse
        });
        return (await SignData(accountToUse.assertAccount(), signable));
    }
    /** @internal */
    _internals(accessToken) {
        if (accessToken !== KeetaUsernameAnchorClientAccessToken) {
            throw (new Error('invalid access token'));
        }
        return ({
            client: this.client,
            logger: this.logger,
            resolver: this.resolver,
            account: this.account,
            signer: this.signer
        });
    }
}
export default KeetaUsernameAnchorClient;
export { KeetaUsernameAnchorProvider };
//# sourceMappingURL=client.js.map