import * as KeetaNetClient from '@keetanetwork/keetanet-client';
import type { AccountPublicKeyString, GenericAccount as KeetaNetGenericAccount } from '@keetanetwork/keetanet-client/lib/account.js';
import * as CurrencyInfo from '@keetanetwork/currency-info';
import type { Logger } from './log/index.ts';
import type { JSONSerializable } from './utils/json.ts';
import type { DeepPartial } from './utils/types.ts';
import type { AssetLocationString, SupportedAssetsMetadata, AssetMovementRailSearchInput, AnchorCustomLocationMetadata } from '../services/asset-movement/common.js';
import type { MovableAssetSearchInput, KeetaNetTokenPublicKeyString } from './asset.js';
import type { NotificationChannelType, NotificationSubscriptionType, SupportedChannelConfigurationMetadata } from '../services/notification/common.js';
import type { ServiceMetadataEndpoint, SharedAnchorCallerCertificateRequirementMetadata, SharedAnchorMetadataLegalExtension, SharedAnchorMetadataSignedExtension } from './metadata.types.js';
import type { VerifiableAccount } from './utils/signing.js';
type ExternalURL = {
    external: '2b828e33-2692-46e9-817e-9b93d63f28fd';
    url: string;
};
type KeetaNetAccount = InstanceType<typeof KeetaNetClient.lib.Account>;
declare const KeetaNetAccount: typeof KeetaNetClient.lib.Account;
type KeetaNetAccountTokenPublicKeyString = ReturnType<InstanceType<typeof KeetaNetClient.lib.Account<typeof KeetaNetAccount.AccountKeyAlgorithm.TOKEN>>['publicKeyString']['get']>;
/**
 * Canonical form of a currency code for use in the ServiceMetadata
 * Which is either the ISO currency code (e.g. "USD", "EUR", "JPY")
 * or a cryptocurrency code prefixed with a dollar sign (e.g. "$BTC", "$ETH")
 */
type ServiceMetadataCurrencyCodeCanonical = CurrencyInfo.ISOCurrencyCode | `$${string}`;
/**
 * Input types which can be used to search for which token represents
 * a given currency or cryptocurrency.
 */
type CurrencySearchInput = ServiceMetadataCurrencyCodeCanonical | CurrencyInfo.ISOCurrencyNumber | CurrencyInfo.Currency;
type CurrencySearchCanonical = ServiceMetadataCurrencyCodeCanonical;
type CountrySearchInput = CurrencyInfo.ISOCountryCode | CurrencyInfo.ISOCountryNumber | CurrencyInfo.Country;
/**
 * Service Metadata General Structure
 */
type ServiceMetadata = {
    version: number;
    /**
     * Map of the currency code to the token public key which
     * represents that currency.
     */
    currencyMap: {
        [currencyCode in ServiceMetadataCurrencyCodeCanonical]?: KeetaNetAccountTokenPublicKeyString;
    };
    services: {
        banking?: {
            [id: string]: SharedAnchorMetadataSignedExtension & {
                operations: {
                    createAccount?: string;
                };
                currencyCodes: string[];
                countryCodes: string[];
                kycProviders?: string[];
            };
        };
        kyc?: {
            [id: string]: SharedAnchorMetadataSignedExtension & {
                operations: {
                    /**
                     * Check if the KYC provider can
                     * service a more specific locality
                     * (optional)
                     */
                    checkLocality?: string;
                    /**
                     * Request an estimate for a KYC
                     * verification (optional)
                     */
                    getEstimate?: string;
                    /**
                     * Begin the KYC verification process
                     * with this KYC provider
                     */
                    createVerification?: string;
                    /**
                     * Get the certificate for the
                     * KYC verification
                     */
                    getCertificates?: string;
                };
                /**
                 * Country codes which this KYC provider can
                 * validate accounts in.  If this is not
                 * specified, then the KYC provider can
                 * validate accounts in any country.
                 */
                countryCodes?: string[];
                /**
                 * The Certificate Authority (CA) Certificate
                 * that this KYC provider uses to sign KYC
                 * certificates.  This is used to identify the
                 * KYC provider.
                 */
                ca: string;
            };
        };
        /**
         * Foreign Exchange (FX) services
         *
         * This is used to identify service providers which
         * can convert currency from one currency to another.
         */
        fx?: {
            /**
             * Provider ID which identifies the FX provider
             */
            [id: string]: SharedAnchorMetadataLegalExtension & SharedAnchorMetadataSignedExtension & {
                operations: {
                    /**
                     * Get an estimate for a currency
                     * conversion (optional)
                     */
                    getEstimate?: string;
                    /**
                     * Get a quote for a currency
                     * conversion
                     */
                    getQuote?: string;
                    /**
                     * Create an exchange to convert
                     * currency
                     */
                    createExchange?: string;
                    /**
                     * Get the status of an exchange
                     * which was previously created
                     */
                    getExchangeStatus?: string;
                };
                /**
                 * Path for which can be used to identify which
                 * currencies this FX provider can convert
                 * between.
                 */
                from: {
                    /**
                     * Currency code which this FX provider can
                     * convert from
                     */
                    currencyCodes: KeetaNetAccountTokenPublicKeyString[];
                    /**
                     * Currency codes which this FX provider can
                     * convert to from the `from.currencyCode`
                     */
                    to: KeetaNetAccountTokenPublicKeyString[];
                    /**
                     * KYC providers which this FX provider
                     * supports (DN) -- if not specified,
                     * then it does not require KYC.
                     */
                    kycProviders?: string[];
                    /**
                     * Operations which this FX provider supports for the specified path (e.g. it may support getting a quote, but not creating an exchange).
                     * If not specified, then it is assumed that the provider supports all operations for the specified path.
                     */
                    supportedAffinities?: {
                        from?: boolean;
                        to?: boolean;
                    };
                }[];
                /**
                 * Asset identifiers in which this FX provider accepts fee
                 * denomination. If not specified, the provider chooses the
                 * fee denomination.
                 */
                acceptedCostAssets?: KeetaNetTokenPublicKeyString[];
            };
        };
        username?: {
            [id: string]: SharedAnchorCallerCertificateRequirementMetadata & SharedAnchorMetadataSignedExtension & {
                operations: {
                    resolve: ServiceMetadataEndpoint;
                    claim?: ServiceMetadataEndpoint;
                    release?: ServiceMetadataEndpoint;
                    search?: ServiceMetadataEndpoint;
                };
                /**
                 * Optional regex pattern which provider-issued unique names must match in order to be valid.
                 * If not specified, then any provider-issued unique name is considered valid as long as it meets the general requirements for provider-issued unique names (e.g. length limits, valid character range).
                 */
                usernamePattern?: string;
            };
        };
        assetMovement?: {
            [id: string]: SharedAnchorMetadataLegalExtension & SharedAnchorMetadataSignedExtension & {
                operations: {
                    [Operation in ('initiateTransfer' | 'simulateTransfer' | 'executeTransfer' | 'getTransferStatus' | 'initiatePersistentForwardingTemplate' | 'createPersistentForwardingTemplate' | 'listPersistentForwardingTemplate' | 'createPersistentForwarding' | 'listPersistentForwarding' | 'listTransactions' | 'shareKYC')]?: ServiceMetadataEndpoint;
                };
                supportedAssets: SupportedAssetsMetadata[];
                locationMetadata?: AnchorCustomLocationMetadata | undefined;
            };
        };
        cards?: {
            [id: string]: {
                workInProgress?: true;
            };
        };
        storage?: {
            [id: string]: SharedAnchorCallerCertificateRequirementMetadata & SharedAnchorMetadataSignedExtension & {
                operations: {
                    put?: ServiceMetadataEndpoint;
                    get?: ServiceMetadataEndpoint;
                    delete?: ServiceMetadataEndpoint;
                    metadata?: ServiceMetadataEndpoint;
                    updateMetadata?: ServiceMetadataEndpoint;
                    search?: ServiceMetadataEndpoint;
                    public?: ServiceMetadataEndpoint;
                    quota?: ServiceMetadataEndpoint;
                };
                /**
                 * Anchor's public key for sharing encrypted containers
                 */
                anchorAccount?: string;
                /**
                 * Published quota limits
                 */
                quotas?: {
                    maxObjectSize: number;
                    maxObjectsPerUser: number;
                    maxStoragePerUser: number;
                    maxSearchLimit: number;
                    maxSignedUrlTTL: number;
                };
                /**
                 * Default TTL in seconds for pre-signed URLs
                 */
                signedUrlDefaultTTL?: number;
                /**
                 * Fields that can be used in search criteria
                 */
                searchableFields?: ('owner' | 'tags' | 'visibility' | 'pathPrefix')[];
            };
        };
        notification?: {
            [id: string]: SharedAnchorCallerCertificateRequirementMetadata & SharedAnchorMetadataSignedExtension & {
                supportedChannels?: Partial<SupportedChannelConfigurationMetadata>;
                supportedSubscriptions?: NotificationSubscriptionType[];
                operations: {
                    registerTarget?: ServiceMetadataEndpoint;
                    listTargets?: ServiceMetadataEndpoint;
                    deleteTarget?: ServiceMetadataEndpoint;
                    createSubscription?: ServiceMetadataEndpoint;
                    listSubscriptions?: ServiceMetadataEndpoint;
                    deleteSubscription?: ServiceMetadataEndpoint;
                };
            };
        };
    };
};
type ServiceMetadataExternalizable = ToJSONValuizable<ServiceMetadata>;
/**
 * Types of services which can be resolved
 */
type Services = keyof ServiceMetadata['services'];
/**
 * Search criteria for each service type
 */
type ServiceSearchCriteria<T extends Services> = {
    'banking': {
        /**
         * Search for a banking provider which supports creating
         * accounts in ALL of the following currencies.
         */
        currencyCodes?: CurrencySearchInput[];
        /**
         * Search for a banking provider which supports creating
         * accounts in ANY of the following countries.
         */
        countryCodes?: CountrySearchInput[];
        /**
         * Search for a banking provider which supports creating
         * accounts verified by ANY of the following KYC providers
         * (DN).
         */
        kycProviders?: string[];
    };
    'fx': {
        /**
         * Search for a provider which can convert from the following
         * input currency
         */
        inputCurrencyCode?: CurrencySearchInput | KeetaNetAccountTokenPublicKeyString;
        /**
         * Search for a provider which can convert to the following
         * output currency
         */
        outputCurrencyCode?: CurrencySearchInput | KeetaNetAccountTokenPublicKeyString;
        /**
         * Search for a provider which supports ANY of the following
         * KYC providers
         */
        kycProviders?: string[];
        /**
         * Search for a provider which supports ALL of the following FX operations
         */
        requiredOperations?: Extract<keyof NonNullable<ServiceMetadata['services']['fx']>[string]['operations'], 'getEstimate' | 'getQuote' | 'createExchange' | 'getExchangeStatus'>[];
        /**
         * Search for a provider which supports the specified affinity
         */
        supportedAffinity?: 'from' | 'to';
    };
    'kyc': {
        /**
         * Search for a KYC provider which can verify accounts in ALL
         * of the following countries.
         */
        countryCodes: CountrySearchInput[];
    };
    'assetMovement': {
        asset?: MovableAssetSearchInput | {
            from: MovableAssetSearchInput;
            to: MovableAssetSearchInput;
        };
        from?: AssetLocationString;
        to?: AssetLocationString;
        /**
         * Rail search criteria
         *
         * @see {AssetMovementRailSearchInput} for details on the structure and behavior of this criteria
         */
        rail?: AssetMovementRailSearchInput;
        /**
         * Search for a provider which supports ANY of the following
         * KYC providers
         */
        kycProviders?: string[];
    };
    /**
     * There are currently no additional filters for searching a username provider
     */
    'username': {};
    'cards': {
        workInProgress: true;
    };
    'storage': {};
    'notification': {
        /**
         * Search for a provider which supports ANY of the following
         */
        supportedChannels?: NotificationChannelType[];
        /**
         * Search for a provider which supports ANY of the following
         */
        supportedSubscriptions?: NotificationSubscriptionType[];
    };
}[T];
type ResolverLookupServiceResults<Service extends Services> = {
    [id: string]: ToValuizableObject<NonNullable<ServiceMetadata['services'][Service]>[string]>;
};
type ServicesMetadataLookupMap = {
    [Service in Services]: {
        criteria: ServiceSearchCriteria<Service>;
        results: ResolverLookupServiceResults<Service>;
    };
};
type JSONSerializablePrimitive = Exclude<JSONSerializable, object>;
type ValuizeInput = JSONSerializablePrimitive | ValuizableObject | ValuizableArray;
type ValuizableArray = (ValuizableMethod | undefined)[];
type ValuizableObject = {
    [key: string]: ValuizableMethod | undefined;
};
type ValuizableKind = 'any' | 'object' | 'array' | 'primitive' | 'string' | 'number' | 'boolean';
interface ValuizableMethodBase {
    (expect?: ValuizableKind): Promise<ValuizeInput>;
    (expect: 'any'): Promise<ValuizeInput>;
}
interface ToValuizableExpectPrimitive<Primitive extends JSONSerializablePrimitive = JSONSerializablePrimitive> extends ValuizableMethodBase {
    (expect: 'primitive'): Promise<Primitive>;
}
interface ValuizableMethod extends ValuizableMethodBase, ToValuizableExpectPrimitive {
    (expect: 'object'): Promise<ValuizableObject>;
    (expect: 'array'): Promise<ValuizableArray>;
    (expect: 'string'): Promise<string>;
    (expect: 'number'): Promise<number>;
    (expect: 'boolean'): Promise<boolean>;
}
interface ToValuizableExpectString<T extends string> extends ValuizableMethodBase, ToValuizableExpectPrimitive<T> {
    (expect: 'string'): Promise<T>;
}
interface ToValuizableExpectNumber extends ValuizableMethodBase, ToValuizableExpectPrimitive<number> {
    (expect: 'number'): Promise<number>;
}
interface ToValuizableExpectBoolean extends ValuizableMethodBase, ToValuizableExpectPrimitive<boolean> {
    (expect: 'boolean'): Promise<boolean>;
}
interface ToValuizableExpectObject<T> extends ValuizableMethodBase {
    (expect: 'object'): Promise<T>;
}
interface ToValuizableExpectArray<T extends unknown[]> extends ValuizableMethodBase {
    (expect: 'array'): Promise<T>;
}
export type ToValuizable<T> = T extends string ? ToValuizableExpectString<T> : T extends number ? ToValuizableExpectNumber : T extends boolean ? ToValuizableExpectBoolean : T extends JSONSerializablePrimitive ? ToValuizableExpectPrimitive<T> : T extends unknown[] ? ToValuizableExpectArray<{
    [K in keyof T]: ToValuizable<T[K]>;
}> : T extends object ? ToValuizableExpectObject<ToValuizableObject<T>> : T extends undefined ? undefined : never;
type ToValuizableObject<T extends object> = {
    [K in keyof T]: ToValuizable<T[K]>;
};
type ToJSONValuizableObject<T extends object> = {
    [K in keyof T]: (T[K] extends object ? ToJSONValuizableObject<T[K]> : T[K] extends (object | undefined) ? ToJSONValuizableObject<NonNullable<T[K]>> | undefined : T[K]) | ExternalURL;
};
type ToJSONValuizable<T> = ToJSONValuizableObject<{
    tmp: T;
}>['tmp'];
type ValuizeResolvable = JSONSerializablePrimitive | ValuizableObject | ValuizableArray | ValuizableMethod;
type URLCacheObjectEntry = {
    pass: true;
    value: JSONSerializable;
    expires: Date;
} | {
    pass: false;
    error: unknown;
    expires: Date;
};
/**
 * A cache object
 */
type URLCacheObject = Map<string, Promise<URLCacheObjectEntry>>;
type ResolverConfig = {
    /**
     * The "root" account(s) to use as the basis for all lookups.  It should
     * contain the authoritative information for resolving in its
     * Metadata.
     *
     * Can be either:
     * - A single KeetaNetGenericAccount
     * - An array of KeetaNetGenericAccount in priority order (highest priority first)
     *
     * When an array is provided, the resolver will merge results from all roots,
     * with entries from higher priority roots taking precedence over lower priority ones.
     */
    root: KeetaNetGenericAccount | KeetaNetGenericAccount[];
    /**
     * A KeetaNet Client to access the network using.
     */
    client: KeetaNetClient.Client | KeetaNetClient.UserClient;
    /**
     * A list of trusted Certificate Authorities to use when connecting to
     * external HTTPS services.
     */
    trustedCAs: string[];
    /**
     * Logger to use for debugging
     */
    logger?: Logger | undefined;
    /**
     * ID for this instance of the resolver
     */
    id?: string;
    /**
     * Caching Parameters
     */
    cache?: Omit<NonNullable<MetadataConfig['cache']>, 'instance'>;
    /**
     * Additional configuration for reading metadata
     */
    metadataConfig?: Pick<MetadataConfig, 'allowInsecureProtocols'>;
};
type MetadataConfig = {
    trustedCAs: ResolverConfig['trustedCAs'];
    client: KeetaNetClient.Client;
    logger?: ResolverConfig['logger'];
    resolver: Resolver;
    cache?: {
        instance: URLCacheObject;
        positiveTTL?: number;
        negativeTTL?: number;
    };
    parent?: Metadata;
    /**
     * Flag indicating if the resolver should read from insecure protocols (ex: http)
     * Defaults to false
     */
    allowInsecureProtocols?: boolean;
};
type ValuizableInstance = {
    value: ValuizableMethod;
};
declare class Metadata implements ValuizableInstance {
    #private;
    private readonly seenURLs;
    private static readonly instanceTypeID;
    static isInstance(value: unknown): value is Metadata;
    /**
     * Format the supplied Metadata as appropriate to be included
     * within the Metadata field of a KeetaNet account to serve
     * as the Metadata for the Resolver.
     */
    static formatMetadata(metadata: ToJSONValuizable<ServiceMetadata>): string;
    static formatMetadata(metadata: JSONSerializable): string;
    /**
     * Assert that the supplied value is a valid Metadata Root Object
     */
    static assertMetadata(value: unknown): asserts value is ToJSONValuizable<ServiceMetadata>;
    /**
     * Check if the supplied value is a Valuizable method which can
     * be called to resolve a Valuizable value.
     */
    static isValuizable(value: unknown): value is ValuizableMethod;
    /**
     * Recursively resolve a Valuizable value into a fully
     * realized JSONSerializable value.  This will walk the
     * entire structure, calling each Valuizable method
     * and replacing it with the returned value.
     *
     * This should only be used in cases where the entire
     * structure needs to be fully realized, as it
     * can be quite expensive.
     */
    static fullyResolveValuizable(value: ValuizeResolvable, invalidReplacement?: JSONSerializable): Promise<JSONSerializable>;
    static fullyResolveValuizable(value: any, invalidReplacement?: JSONSerializable): Promise<JSONSerializable>;
    constructor(url: string | URL, config: MetadataConfig);
    /**
     * @param metadata Metadata to parse -- base64 encoded string or ArrayBuffer
     */
    private parseMetadata;
    private readKeetaNetURL;
    private readHTTPSURL;
    private readURL;
    private resolveValue;
    private assertValuizableKind;
    private valuize;
    value(expect: 'object'): Promise<ValuizableObject>;
    value(expect: 'array'): Promise<ValuizableArray>;
    value(expect: 'primitive'): Promise<JSONSerializablePrimitive>;
    value(expect: 'string'): Promise<string>;
    value(expect: 'number'): Promise<number>;
    value(expect: 'boolean'): Promise<boolean>;
    value(expect: 'any'): Promise<ValuizeInput>;
    value(expect?: ValuizableKind): Promise<ValuizeInput>;
}
type ResolverStats = {
    keetanet: {
        reads: number;
    };
    https: {
        reads: number;
    };
    unsupported: {
        reads: number;
    };
    reads: number;
    cache: {
        hit: number;
        miss: number;
    };
};
type SharedLookupCriteria = {
    providerIDs?: string[];
    /**
     * Restrict to entries signed by one of the listed accounts. Each entry
     * may be a {@link KeetaNetGenericAccount} or its public-key string
     * form. Entries without a matching `account` are filtered out
     * (including unsigned entries).
     */
    accounts?: (AccountPublicKeyString | VerifiableAccount)[];
};
declare class Resolver {
    #private;
    readonly id: string;
    static readonly Metadata: typeof Metadata;
    private readonly lookupMap;
    constructor(config: ResolverConfig);
    get stats(): ResolverStats;
    private lookupBankingServices;
    private lookupKYCServices;
    private lookupFXServices;
    private lookupNotificationServices;
    filterSupportedAssets(assetService: ValuizableObject, criteria?: ServiceSearchCriteria<'assetMovement'>): Promise<SupportedAssetsMetadata[]>;
    private lookupAssetMovementServices;
    private lookupUsernameServices;
    private lookupStorageServices;
    getRootMetadata(): Promise<ToValuizableObject<Pick<ServiceMetadata, 'version'> & DeepPartial<Omit<ServiceMetadata, 'version'>>>>;
    listTransferableAssets(): Promise<KeetaNetAccountTokenPublicKeyString[]>;
    listTokens(): Promise<{
        token: KeetaNetAccountTokenPublicKeyString;
        currency: CurrencySearchCanonical;
    }[]>;
    listSupportedKYCCountries(): Promise<CurrencyInfo.Country[]>;
    lookupToken(currencyCode: CurrencySearchInput | KeetaNetAccountTokenPublicKeyString): Promise<{
        token: KeetaNetAccountTokenPublicKeyString;
        currency: CurrencySearchCanonical;
    } | null>;
    lookup<T extends keyof ServicesMetadataLookupMap>(service: T, criteria: ServicesMetadataLookupMap[T]['criteria'], sharedCriteria?: SharedLookupCriteria): Promise<ServicesMetadataLookupMap[T]['results'] | undefined>;
    clearCache(): void;
}
export default Resolver;
export type { ServiceMetadata, ServiceMetadataExternalizable, ServiceSearchCriteria, Services, SharedLookupCriteria };
export type { ServiceMetadataEndpoint, ServiceMetadataAuthenticationType } from './metadata.types.js';
//# sourceMappingURL=resolver.d.ts.map