import { FeatureFlags, Field, PrivateKey, Provable, ProvableType, PublicKey, Signature, UInt32, Unconstrained, VerificationKey } from 'o1js';
import { Spec, type Input, type Claims } from './program-spec.ts';
import { type Program } from './program.ts';
import { type CredentialSpec, type StoredCredential } from './credential.ts';
import { type NetworkId, type WalletDerivedContext, type HttpsInputContext, type HttpsWalletContext, type ZkAppInputContext } from './context.ts';
export { PresentationRequest, HttpsRequest, ZkAppRequest, Presentation, ProvablePresentation, };
export { type PresentationRequestType, pickCredentials };
type PresentationRequestType = 'no-context' | 'zk-app' | 'https';
type PresentationRequest<RequestType extends PresentationRequestType = PresentationRequestType, Output = any, Inputs extends Record<string, Input> = Record<string, Input>, InputContext = any, WalletContext = any> = {
    type: RequestType;
    spec: Spec<Output, Inputs>;
    claims: Claims<Inputs>;
    inputContext: InputContext;
    program?: unknown;
    verificationKey?: VerificationKey;
    deriveContext(
    /**
     * Context that is passed in from the input request / server-side
     */
    inputContext: InputContext, 
    /**
     * Application-specific context that is passed in from the wallet / client-side
     */
    walletContext: WalletContext, 
    /**
     * Context automatically (re-)derived on the client
     */
    derivedContext: WalletDerivedContext): Field;
};
type CompiledRequest<Output, Inputs extends Record<string, Input>> = {
    spec: Spec<Output, Inputs>;
    program: Program<Output, Inputs>;
    verificationKey: VerificationKey;
    ProvablePresentation: typeof ProvablePresentation<Output, Inputs> & {
        from(input: Presentation): ProvablePresentation<Output, Inputs>;
        provable: Provable<ProvablePresentation<Output, Inputs>, Presentation<Output, Inputs>>;
    };
};
declare const PresentationRequest: {
    https<Output, Inputs extends Record<string, Input>>(spec: Spec<Output, Inputs>, claims: Claims<Inputs>, context: {
        action: string;
    }): HttpsRequest<Output, Inputs>;
    httpsFromCompiled<Output, Inputs extends Record<string, Input>>(compiled: CompiledRequest<Output, Inputs>, claims: Claims<Inputs>, context: {
        action: string;
    }): HttpsRequest<Output, Inputs>;
    zkApp<Output, Inputs extends Record<string, Input>>(spec: Spec<Output, Inputs>, claims: Claims<Inputs>, context: {
        publicKey: PublicKey;
        tokenId?: Field;
        methodName: string;
        network: NetworkId;
        nonce?: UInt32;
    }): ZkAppRequest<Output, Inputs>;
    zkAppFromCompiled<Output, Inputs extends Record<string, Input>>(compiled: CompiledRequest<Output, Inputs>, claims: Claims<Inputs>, context: {
        publicKey: PublicKey;
        tokenId?: Field;
        methodName: string;
        network?: NetworkId;
        nonce?: UInt32;
    }): ZkAppRequest<Output, Inputs>;
    noContext<Output, Inputs extends Record<string, Input>>(spec: Spec<Output, Inputs>, claims: Claims<Inputs>): NoContextRequest<Output, Inputs>;
    toJSON(request: PresentationRequest): string;
    fromJSON<R extends RequestFromType<K>, K extends PresentationRequestType = PresentationRequestType>(expectedType: K, json: string): R;
};
type Presentation<Output = any, Inputs extends Record<string, Input> = Record<string, Input>> = {
    version: 'v0';
    claims: Claims<Inputs>;
    outputClaim: Output;
    serverNonce: Field;
    clientNonce: Field;
    proof: {
        proof: string;
        maxProofsVerified: 0 | 1 | 2;
    };
};
type Output<R> = R extends PresentationRequest<any, infer O> ? O : never;
type Inputs<R> = R extends PresentationRequest<any, any, infer I> ? I : never;
type WalletContext<R> = R extends PresentationRequest<any, any, any, any, infer W> ? W : never;
declare const Presentation: {
    precompile<Output, Inputs extends Record<string, Input>>(spec: Spec<Output, Inputs>): Promise<CompiledRequest<Output, Inputs>>;
    compile<R extends PresentationRequest>(request: R): Promise<Omit<R, "program"> & {
        program: Program<Output<R>, Inputs<R>>;
        verificationKey: VerificationKey;
    }>;
    /**
     * Create a presentation, given the request, context, and credentials.
     *
     * The first argument is the private key of the credential's owner, which is needed to sign credentials.
     */
    create: typeof createPresentation;
    /**
     * Prepare a presentation, given the request, context, and credentials
     *
     * This way creating the presentation doesn't require the private key of the owner but
     * instead lets the wallet to handle the signing process
     */
    prepare: typeof preparePresentation;
    /**
     * Finalize presentation given request, signature, and prepared data from preparePresentation
     */
    finalize: typeof finalizePresentation;
    /**
     * Verify a presentation against a request and context.
     *
     * Returns the verified output claim of the proof, to be consumed by application-specific logic.
     */
    verify: typeof verifyPresentation;
    /**
     * Serialize a presentation to JSON.
     */
    toJSON: typeof toJSON;
    /**
     * Deserialize a presentation from JSON.
     */
    fromJSON: typeof fromJSON;
};
declare function preparePresentation<R extends PresentationRequest>({ request, context: walletContext, credentials, }: {
    request: R;
    context: WalletContext<R>;
    credentials: (StoredCredential & {
        key?: string;
    })[];
}): Promise<{
    context: Field;
    messageFields: string[];
    credentialsUsed: Record<string, StoredCredential>;
    serverNonce: Field;
    clientNonce: Field;
    compiledRequest: CompiledRequest<Output<R>, Inputs<R>>;
}>;
declare function finalizePresentation<R extends PresentationRequest>(request: R, ownerSignature: Signature, preparedData: {
    serverNonce: Field;
    clientNonce: Field;
    context: Field;
    credentialsUsed: Record<string, StoredCredential>;
    compiledRequest: {
        program: Program<Output<R>, Inputs<R>>;
    };
}): Promise<Presentation<Output<R>, Inputs<R>>>;
declare function createPresentation<R extends PresentationRequest>(ownerKey: PrivateKey, params: {
    request: R;
    context: WalletContext<R>;
    credentials: (StoredCredential & {
        key?: string;
    })[];
}): Promise<Presentation<Output<R>, Inputs<R>>>;
declare function verifyPresentation<R extends PresentationRequest>(request: R, presentation: Presentation<any, Record<string, any>>, context: WalletContext<R>): Promise<Output<R>>;
declare function toJSON<Output, Inputs extends Record<string, Input>>(presentation: Presentation<Output, Inputs>): string;
declare function fromJSON(presentationJson: string): Presentation;
declare function pickCredentials(spec: Spec, [...credentials]: (StoredCredential & {
    key?: string;
})[]): {
    credentialsUsed: Record<string, StoredCredential>;
    credentialsAndSpecs: (StoredCredential & {
        spec: CredentialSpec;
    })[];
};
type RequestFromType<Type extends PresentationRequestType, Output = any, Inputs extends Record<string, Input> = Record<string, Input>> = Type extends 'no-context' ? NoContextRequest<Output, Inputs> : Type extends 'zk-app' ? ZkAppRequest<Output, Inputs> : Type extends 'https' ? HttpsRequest<Output, Inputs> : never;
type NoContextRequest<Output = any, Inputs extends Record<string, Input> = Record<string, Input>> = PresentationRequest<'no-context', Output, Inputs, undefined, undefined>;
type HttpsRequest<Output = any, Inputs extends Record<string, Input> = Record<string, Input>> = PresentationRequest<'https', Output, Inputs, HttpsInputContext, HttpsWalletContext>;
type ZkAppRequest<Output = any, Inputs extends Record<string, Input> = Record<string, Input>> = PresentationRequest<'zk-app', Output, Inputs, ZkAppInputContext, undefined>;
declare function HttpsRequest<Output, Inputs extends Record<string, Input>>(request: {
    spec: Spec<Output, Inputs>;
    claims: Claims<Inputs>;
    inputContext: HttpsInputContext;
    program?: Program<Output, Inputs>;
    verificationKey?: VerificationKey;
}): HttpsRequest<Output, Inputs>;
declare function ZkAppRequest<Output, Inputs extends Record<string, Input>>(request: {
    spec: Spec<Output, Inputs>;
    claims: Claims<Inputs>;
    inputContext: ZkAppInputContext;
    program?: Program<Output, Inputs>;
    verificationKey?: VerificationKey;
}): ZkAppRequest<Output, Inputs>;
/**
 * Presentation that can be verified inside a zkApp.
 *
 * Create a subclass for your presentation as follows:
 *
 * ```ts
 * let compiled = await Presentation.precompile(spec);
 * class ProvablePresentation extends compiled.ProvablePresentation {}
 * ```
 */
declare class ProvablePresentation<Output = any, Inputs extends Record<string, Input> = any> {
    claims: Claims<Inputs>;
    outputClaim: Output;
    clientNonce: Field;
    serverNonce: Unconstrained<bigint>;
    proof: Unconstrained<string>;
    constructor(input: {
        claims: Claims<Inputs>;
        outputClaim: Output;
        clientNonce: Field;
        serverNonce: Unconstrained<bigint>;
        proof: Unconstrained<string>;
    });
    compiledRequest(): {
        claimsType: ProvableType<Claims<Inputs>>;
        outputClaimType: ProvableType<Output>;
        tagName: string;
        verificationKey: VerificationKey;
        maxProofsVerified: 0 | 1 | 2;
        featureFlags: FeatureFlags;
    };
    /**
     * Verify presentation in a provable context.
     *
     * Input is the zkApp which this presentation is verified in.
     *
     * Pass in the public key, token id and current method of your zkapp to make sure
     * you don't accept presentations that were intended for a different context.
     *
     * Optionally, you can further restrict context by passing in the network and nonce.
     */
    verify(context: {
        publicKey: PublicKey;
        tokenId: Field;
        methodName: string;
        network?: NetworkId;
        nonce?: UInt32;
    }): {
        claims: Claims<Inputs>;
        outputClaim: Output;
    };
    static get provable(): Provable<ProvablePresentation, Presentation<any, any>>;
}
