import { TransactionRequest, Provider } from '@ethersproject/abstract-provider';
import { TypedDataDomain, TypedDataField } from '@ethersproject/abstract-signer';
import { IAgentContext, IKeyManager, IKey } from '@veramo/core';
import { Signer, ethers, TypedDataDomain as TypedDataDomain$1, TypedDataField as TypedDataField$1 } from 'ethers';
import { Deferrable } from '@ethersproject/properties';
import { ExpressSupport, ISingleEndpointOpts } from '@sphereon/ssi-express-support';

type rpcMethods = 'eth_call' | 'eth_getBalance';
interface IWeb3Provider {
    isMetaMask?: boolean;
    request(args: {
        method: 'eth_call';
        params: any[];
    }): Promise<any>;
    request(args: {
        method: 'eth_getBalance';
        params: string[];
    }): Promise<string>;
    request(args: {
        method: 'eth_accounts';
        params: [];
    }): Promise<string[]>;
    request(args: {
        method: 'eth_requestAccounts';
        params: [];
    }): Promise<string[]>;
    request(args: {
        method: 'net_version';
        params: [];
    }): Promise<number>;
    request(args: {
        method: 'eth_chainId';
        params: [];
    }): Promise<string>;
    request(args: {
        method: 'personal_sign';
        params: string[];
    }): Promise<string>;
    request(args: {
        method: 'eth_signTypedData' | 'eth_signTypedData_v1';
        params: [object[], string];
    }): Promise<string>;
    request(args: {
        method: 'eth_signTypedData_v3' | 'eth_signTypedData_v4';
        params: string[];
    }): Promise<string>;
    request(args: {
        method: 'eth_sendTransaction';
        params: TransactionRequest[];
    }): Promise<string>;
    request(args: {
        method: rpcMethods | string;
        params?: any[];
    }): Promise<any>;
    emit(eventName: string, ...args: any[]): void;
    on(eventName: string, listener: (eventName: string) => void): void;
}
type IRequiredContext = IAgentContext<IKeyManager>;
interface PendingRequest {
    requestInfo: {
        method: string;
        params: any[];
    };
    reject: (err: {
        message?: string;
        code?: number;
    }) => void;
    authorize: () => Promise<void>;
}
interface ChainConnection {
    chainId: number;
    rpcUrl: string;
}
interface Web3ProviderConfig {
    debug?: boolean;
    logger: typeof console.log;
}
interface TypedDataSigner {
    _signTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): Promise<string>;
}
declare enum Web3Method {
    RequestAccounts = "eth_requestAccounts",
    Accounts = "eth_accounts",
    SendTransaction = "eth_sendTransaction",
    SwitchEthereumChain = "wallet_switchEthereumChain",
    AddEthereumChain = "wallet_addEthereumChain",
    SignMessage = "personal_sign",
    SignTypedData = "eth_signTypedData",
    SignTypedDataV1 = "eth_signTypedData_v1",
    SignTypedDataV3 = "eth_signTypedData_v3",
    SignTypedDataV4 = "eth_signTypedData_v4"
}
declare function without<T>(list: T[], item: T): T[];

declare class ErrorWithCode extends Error {
    code?: number | undefined;
    constructor(message?: string, code?: number | undefined);
}

declare class EventEmitter {
    private readonly listeners;
    emit(eventName: string, ...args: any[]): boolean;
    on(eventName: string, listener: (...args: any[]) => void): this;
    off(eventName: string, listener: (...args: any[]) => void): this;
    once(eventName: string, listener: (...args: any[]) => void): this;
}

declare class EthersHeadlessProvider extends EventEmitter implements IWeb3Provider {
    private readonly chains;
    private _pendingRequests;
    private _signers;
    private _activeChainId;
    private _rpc;
    private _config;
    private _authorizedRequests;
    constructor(signers: Signer[], chains: ChainConnection[], config?: Web3ProviderConfig);
    request(args: {
        method: 'eth_call';
        params: any[];
    }): Promise<any>;
    request(args: {
        method: 'eth_getBalance';
        params: string[];
    }): Promise<string>;
    request(args: {
        method: 'eth_accounts';
        params: [];
    }): Promise<string[]>;
    request(args: {
        method: 'eth_requestAccounts';
        params: string[];
    }): Promise<string[]>;
    request(args: {
        method: 'net_version';
        params: [];
    }): Promise<number>;
    request(args: {
        method: 'eth_chainId';
        params: [];
    }): Promise<string>;
    request(args: {
        method: 'personal_sign';
        params: string[];
    }): Promise<string>;
    request(args: {
        method: 'eth_signTypedData' | 'eth_signTypedData_v1';
        params: [object[], string];
    }): Promise<string>;
    request(args: {
        method: 'eth_signTypedData_v3' | 'eth_signTypedData_v4';
        params: string[];
    }): Promise<string>;
    request(args: {
        method: 'eth_sendTransaction';
        params: TransactionRequest[];
    }): Promise<string>;
    getCurrentWallet(): Signer;
    waitAuthorization<T>(requestInfo: PendingRequest['requestInfo'], task: () => Promise<T>, permanentPermission?: boolean, methodOverride?: string): Promise<unknown>;
    private consumeRequest;
    private consumeAllRequests;
    getPendingRequests(): PendingRequest['requestInfo'][];
    getPendingRequestCount(requestKind?: Web3Method): number;
    authorize(requestKind: Web3Method): Promise<void>;
    reject(requestKind: Web3Method, reason?: ErrorWithCode): Promise<void>;
    authorizeAll(): void;
    rejectAll(reason?: ErrorWithCode): void;
    changeAccounts(signers: Signer[]): Promise<void>;
    private getCurrentChain;
    getRpc(): ethers.providers.JsonRpcProvider;
    getNetwork(): ChainConnection;
    getNetworks(): ChainConnection[];
    addNetwork(chainId: number, rpcUrl: string): void;
    switchNetwork(chainId: number): void;
}

declare class EthersKMSSignerBuilder {
    private context?;
    private keyRef?;
    private provider?;
    withContext(context: IRequiredContext): this;
    withKid(kid: string): this;
    withKeyRef(keyRef: Pick<IKey, 'kid'> | string): this;
    withProvider(provider: ethers.providers.Provider): this;
    build(): EthersKMSSigner;
}
/**
 * This is a Ethers signer that delegates back to the KMS for the actual signatures.
 * This means we do not expose private keys and can use any Secp256k1 key stored in the KMS if we want
 *
 * Be aware that the provided KeyRef needs to belong to the respective KMS, as it will use a lookup for the key in the KMS to sign
 */
declare class EthersKMSSigner extends Signer implements TypedDataSigner {
    private readonly context;
    private readonly keyRef;
    constructor({ provider, context, keyRef }: {
        provider?: ethers.providers.Provider;
        context: IRequiredContext;
        keyRef: Pick<IKey, 'kid'>;
    });
    getAddress(): Promise<string>;
    signTransaction(transaction: Deferrable<TransactionRequest>): Promise<string>;
    signRaw(message: string | Uint8Array): Promise<string>;
    signMessage(message: string | Uint8Array): Promise<string>;
    _signTypedData(domain: TypedDataDomain$1, types: Record<string, Array<TypedDataField$1>>, value: Record<string, any>): Promise<string>;
    connect(provider?: Provider): EthersKMSSigner;
}

type Fn = (...args: any[]) => any;
declare function createWeb3Provider(signers: Signer[], chainId: number | number[], rpcUrl: string, evaluate?: <T extends keyof IWeb3Provider>(method: T, ...args: IWeb3Provider[T] extends Fn ? Parameters<IWeb3Provider[T]> : []) => Promise<void>, config?: Web3ProviderConfig): IWeb3Provider;

declare function getAddressFromAgent(context: IRequiredContext, keyRef: Pick<IKey, 'kid'>): Promise<string>;
declare function getKey(context: IRequiredContext, keyRef: Pick<IKey, 'kid'>): Promise<IKey | undefined>;

declare function createRpcServer(provider: EthersHeadlessProvider, expressSupport: ExpressSupport, opts?: ISingleEndpointOpts & {
    basePath?: string;
}): void;
declare function createServiceMethod(method: string, service: Record<string, Function>, provider: EthersHeadlessProvider): void;
declare function createService(provider: EthersHeadlessProvider): {};

export { type ChainConnection, EthersHeadlessProvider, EthersKMSSigner, EthersKMSSignerBuilder, EventEmitter, type IRequiredContext, type IWeb3Provider, type PendingRequest, type TypedDataSigner, Web3Method, type Web3ProviderConfig, createRpcServer, createService, createServiceMethod, createWeb3Provider, getAddressFromAgent, getKey, type rpcMethods, without };
