import { EventEmitter } from 'eventemitter3';
import type * as Address from './Address.js';
import * as Errors from './Errors.js';
import type * as RpcSchema_internal from './internal/rpcSchema.js';
import type { Compute, IsNarrowable, IsNever } from './internal/types.js';
import * as RpcResponse from './RpcResponse.js';
import type * as RpcSchema from './RpcSchema.js';
/** Options for a {@link ox#Provider.Provider}. */
export type Options = {
    /**
     * RPC Schema to use for the Provider's `request` function.
     * See {@link ox#RpcSchema.(from:function)} for more.
     *
     * @default `RpcSchema.Generic`
     */
    schema?: RpcSchema.Schema | undefined;
};
/** Root type for an EIP-1193 Provider. */
export type Provider<options extends Options | undefined = undefined, eventMap extends boolean | Record<string, unknown> = false, _schema extends RpcSchema.Generic = options extends {
    schema: infer schema extends RpcSchema.Schema;
} ? RpcSchema.ToGeneric<schema> : RpcSchema.Default> = Compute<{
    request: RequestFn<_schema>;
} & ((eventMap extends true ? Emitter<EventMap> : never) | (eventMap extends false ? Partial<Emitter<EventMap>> : never) | (eventMap extends Record<string, unknown> ? Emitter<eventMap> : never))>;
/** Type for an EIP-1193 Provider's event emitter. */
export type Emitter<eventMap extends Record<string, unknown> | undefined = undefined> = Compute<EventEmitter<EventMap<eventMap>>>;
/** EIP-1193 Provider's `request` function. */
export type RequestFn<schema extends RpcSchema.Generic = RpcSchema.Generic> = <methodName extends RpcSchema.MethodNameGeneric>(parameters: RpcSchema_internal.ExtractRequestOpaque<schema, methodName>) => Promise<RpcSchema.ExtractReturnType<schema, methodName>>;
export type ConnectInfo = {
    chainId: string;
};
export type Message = {
    type: string;
    data: unknown;
};
export declare class ProviderRpcError extends Error {
    name: string;
    code: number;
    details: string;
    constructor(code: number, message: string);
}
export type EventMap<eventMap extends Record<string, unknown> | undefined = undefined> = {
    accountsChanged: (accounts: readonly Address.Address[]) => void;
    chainChanged: (chainId: string) => void;
    connect: (connectInfo: ConnectInfo) => void;
    disconnect: (error: ProviderRpcError) => void;
    message: (message: Message) => void;
} & (eventMap extends Record<string, unknown> ? eventMap : {});
/** The user rejected the request. */
export declare class UserRejectedRequestError extends ProviderRpcError {
    static readonly code = 4001;
    readonly code = 4001;
    readonly name = "Provider.UserRejectedRequestError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** The requested method and/or account has not been authorized by the user. */
export declare class UnauthorizedError extends ProviderRpcError {
    static readonly code = 4100;
    readonly code = 4100;
    readonly name = "Provider.UnauthorizedError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** The provider does not support the requested method. */
export declare class UnsupportedMethodError extends ProviderRpcError {
    static readonly code = 4200;
    readonly code = 4200;
    readonly name = "Provider.UnsupportedMethodError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** The provider is disconnected from all chains. */
export declare class DisconnectedError extends ProviderRpcError {
    static readonly code = 4900;
    readonly code = 4900;
    readonly name = "Provider.DisconnectedError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** The provider is not connected to the requested chain. */
export declare class ChainDisconnectedError extends ProviderRpcError {
    static readonly code = 4901;
    readonly code = 4901;
    readonly name = "Provider.ChainDisconnectedError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** An error occurred when attempting to switch chain. */
export declare class SwitchChainError extends ProviderRpcError {
    static readonly code = 4902;
    readonly code = 4902;
    readonly name = "Provider.SwitchChainError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** This Wallet does not support a capability that was not marked as optional. */
export declare class UnsupportedNonOptionalCapabilityError extends ProviderRpcError {
    static readonly code = 5700;
    readonly code = 5700;
    readonly name = "Provider.UnsupportedNonOptionalCapabilityError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** This Wallet does not support the requested chain ID. */
export declare class UnsupportedChainIdError extends ProviderRpcError {
    static readonly code = 5710;
    readonly code = 5710;
    readonly name = "Provider.UnsupportedChainIdError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** There is already a bundle submitted with this ID. */
export declare class DuplicateIdError extends ProviderRpcError {
    static readonly code = 5720;
    readonly code = 5720;
    readonly name = "Provider.DuplicateIdError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** This bundle id is unknown / has not been submitted. */
export declare class UnknownBundleIdError extends ProviderRpcError {
    static readonly code = 5730;
    readonly code = 5730;
    readonly name = "Provider.UnknownBundleIdError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** The call bundle is too large for the Wallet to process. */
export declare class BundleTooLargeError extends ProviderRpcError {
    static readonly code = 5740;
    readonly code = 5740;
    readonly name = "Provider.BundleTooLargeError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** The Wallet can support atomicity after an upgrade, but the user rejected the upgrade. */
export declare class AtomicReadyWalletRejectedUpgradeError extends ProviderRpcError {
    static readonly code = 5750;
    readonly code = 5750;
    readonly name = "Provider.AtomicReadyWalletRejectedUpgradeError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/** The wallet does not support atomic execution but the request requires it. */
export declare class AtomicityNotSupportedError extends ProviderRpcError {
    static readonly code = 5760;
    readonly code = 5760;
    readonly name = "Provider.AtomicityNotSupportedError";
    constructor({ message, }?: {
        message?: string | undefined;
    });
}
/**
 * Creates an EIP-1193 flavored event emitter to be injected onto a Provider.
 *
 * @example
 * ```ts twoslash
 * // @noErrors
 * import { Provider, RpcRequest, RpcResponse } from 'ox' // [!code focus]
 *
 * // 1. Instantiate a Provider Emitter. // [!code focus]
 * const emitter = Provider.createEmitter() // [!code focus]
 *
 * const store = RpcRequest.createStore()
 *
 * const provider = Provider.from({
 *   // 2. Pass the Emitter to the Provider. // [!code focus]
 *   ...emitter, // [!code focus]
 *   async request(args) {
 *     return await fetch('https://1.rpc.thirdweb.com', {
 *       body: JSON.stringify(store.prepare(args)),
 *       method: 'POST',
 *       headers: {
 *         'Content-Type': 'application/json'
 *       }
 *     })
 *       .then((res) => res.json())
 *       .then(RpcResponse.parse)
 *   }
 * })
 *
 * // 3. Emit Provider Events. // [!code focus]
 * emitter.emit('accountsChanged', ['0x...']) // [!code focus]
 * ```
 *
 * @returns An event emitter.
 */
export declare function createEmitter<eventMap extends Record<string, unknown> = Record<string, unknown>>(): Emitter<eventMap>;
export declare namespace createEmitter {
    type ErrorType = Errors.GlobalErrorType;
}
/**
 * Instantiates an [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) {@link ox#Provider.Provider}
 * from an arbitrary [EIP-1193 Provider](https://eips.ethereum.org/EIPS/eip-1193) interface.
 *
 * @example
 * ### Instantiating with RPC Transport
 *
 * Ox's {@link ox#RpcTransport} is EIP-1193 compliant, and can be used to instantiate an EIP-1193 Provider. This means you can use any HTTP RPC endpoint as an EIP-1193 Provider.
 *
 * ```ts twoslash
 * import { Provider, RpcTransport } from 'ox'
 *
 * const transport = RpcTransport.fromHttp(
 *   'https://1.rpc.thirdweb.com'
 * )
 * const provider = Provider.from(transport)
 * ```
 *
 * @example
 * ### Instantiating with External Providers
 *
 * The example below demonstrates how we can instantiate a typed EIP-1193 Provider from an
 * external EIP-1193 Provider like `window.ethereum`.
 *
 * ```ts twoslash
 * import 'ox/window'
 * import { Provider } from 'ox'
 *
 * const provider = Provider.from(window.ethereum)
 *
 * const blockNumber = await provider.request({
 *   method: 'eth_blockNumber'
 * })
 * ```
 *
 * :::tip
 *
 * There are also libraries that distribute EIP-1193 Provider objects that you can use with `Provider.from`:
 *
 * - [`@walletconnect/ethereum-provider`](https://www.npmjs.com/package/\@walletconnect/ethereum-provider)
 *
 * - [`@coinbase/wallet-sdk`](https://www.npmjs.com/package/\@coinbase/wallet-sdk)
 *
 * - [`@metamask/detect-provider`](https://www.npmjs.com/package/\@metamask/detect-provider)
 *
 * - [`@safe-global/safe-apps-provider`](https://github.com/safe-global/safe-apps-sdk/tree/main/packages/safe-apps-provider)
 *
 * - [`mipd`](https://github.com/wevm/mipd): EIP-6963 Multi Injected Providers
 *
 * :::
 *
 * @example
 * ### Instantiating a Custom Provider
 *
 * The example below demonstrates how we can instantiate a typed EIP-1193 Provider from a
 * HTTP `fetch` JSON-RPC request. You can use this pattern to integrate with any asynchronous JSON-RPC
 * transport, including WebSockets and IPC.
 *
 * ```ts twoslash
 * // @noErrors
 * import { Provider, RpcRequest, RpcResponse } from 'ox'
 *
 * const store = RpcRequest.createStore()
 *
 * const provider = Provider.from({
 *   async request(args) {
 *     return await fetch('https://1.rpc.thirdweb.com', {
 *       body: JSON.stringify(store.prepare(args)),
 *       method: 'POST',
 *       headers: {
 *         'Content-Type': 'application/json'
 *       }
 *     })
 *       .then((res) => res.json())
 *       .then(RpcResponse.parse)
 *   }
 * })
 *
 * const blockNumber = await provider.request({
 *   method: 'eth_blockNumber'
 * })
 * ```
 *
 * @example
 * ### Type-safe Custom Schemas
 *
 * It is possible to define your own type-safe schema by using the {@link ox#RpcSchema.(from:function)} type.
 *
 * ```ts twoslash
 * // @noErrors
 * import 'ox/window'
 * import { Provider, RpcSchema } from 'ox'
 *
 * const schema = RpcSchema.from<
 *   | RpcSchema.Default
 *   | {
 *       Request: {
 *         method: 'abe_foo'
 *         params: [id: number]
 *       }
 *       ReturnType: string
 *     }
 *   | {
 *       Request: {
 *         method: 'abe_bar'
 *         params: [id: string]
 *       }
 *       ReturnType: string
 *     }
 * >()
 *
 * const provider = Provider.from(window.ethereum, { schema })
 *
 * const blockNumber = await provider.request({ method: 'e' })
 * //                                                    ^|
 * ```
 *
 * @example
 * ### Instantiating a Provider with Events
 *
 * The example below demonstrates how to instantiate a Provider with your own EIP-1193 flavored event emitter.
 *
 * This example is useful for Wallets that distribute an EIP-1193 Provider (e.g. webpage injection via `window.ethereum`).
 *
 * ```ts twoslash
 * // @noErrors
 * import { Provider, RpcRequest, RpcResponse } from 'ox'
 *
 * // 1. Instantiate a Provider Emitter.
 * const emitter = Provider.createEmitter() // [!code ++]
 *
 * const store = RpcRequest.createStore()
 *
 * const provider = Provider.from({
 *   // 2. Pass the Emitter to the Provider.
 *   ...emitter, // [!code ++]
 *   async request(args) {
 *     return await fetch('https://1.rpc.thirdweb.com', {
 *       body: JSON.stringify(store.prepare(args)),
 *       method: 'POST',
 *       headers: {
 *         'Content-Type': 'application/json'
 *       }
 *     })
 *       .then((res) => res.json())
 *       .then(RpcResponse.parse)
 *   }
 * })
 *
 * // 3. Emit Provider Events.
 * emitter.emit('accountsChanged', ['0x...']) // [!code ++]
 * ```
 *
 * @param provider - The EIP-1193 provider to convert.
 * @returns An typed EIP-1193 Provider.
 */
export declare function from<options extends Options | undefined, provider extends from.Value<options> | undefined = undefined>(provider: provider | from.Value<options> | undefined, options?: options | Options): from.ReturnType<options, provider>;
export declare namespace from {
    type Value<options extends Options | undefined = undefined> = Partial<Emitter<any>> & {
        request: (parameters: options extends {
            schema: infer schema extends RpcSchema.Schema;
        } ? RpcSchema.ToGeneric<schema>['Request'] : RpcSchema.Generic['Request']) => unknown;
    };
    type ReturnType<options extends Options | undefined = Options | undefined, provider extends from.Value<options> | undefined = from.Value<options> | undefined> = Omit<provider, 'request'> & {
        request: RequestFn<options extends {
            schema: infer schema extends RpcSchema.Schema;
        } ? RpcSchema.ToGeneric<schema> : RpcSchema.Default>;
    };
    type ErrorType = IsUndefinedError | Errors.GlobalErrorType;
}
/**
 * Parses an error into a Provider error instance.
 *
 * @example
 * ```ts twoslash
 * import { Provider } from 'ox'
 *
 * const error = Provider.parseError({
 *   code: 4200,
 *   message: 'foo'
 * })
 *
 * error
 * // ^?
 * ```
 *
 * @param error - The error object to parse.
 * @returns An error instance.
 */
export declare function parseError<const error extends RpcResponse.ErrorObject | Error | unknown>(error: error | Error | RpcResponse.ErrorObject): parseError.ReturnType<error>;
export declare namespace parseError {
    type ReturnType<errorObject extends RpcResponse.ErrorObject | unknown, error = errorObject extends RpcResponse.ErrorObject ? (errorObject['code'] extends DisconnectedError['code'] ? DisconnectedError : never) | (IsNarrowable<errorObject['code'], number> extends false ? DisconnectedError : never) | (errorObject['code'] extends ChainDisconnectedError['code'] ? ChainDisconnectedError : never) | (IsNarrowable<errorObject['code'], number> extends false ? ChainDisconnectedError : never) | (errorObject['code'] extends UserRejectedRequestError['code'] ? UserRejectedRequestError : never) | (IsNarrowable<errorObject['code'], number> extends false ? UserRejectedRequestError : never) | (errorObject['code'] extends UnauthorizedError['code'] ? UnauthorizedError : never) | (IsNarrowable<errorObject['code'], number> extends false ? UnauthorizedError : never) | (errorObject['code'] extends UnsupportedMethodError['code'] ? UnsupportedMethodError : never) | (IsNarrowable<errorObject['code'], number> extends false ? UnsupportedMethodError : never) | (errorObject['code'] extends SwitchChainError['code'] ? SwitchChainError : never) | (IsNarrowable<errorObject['code'], number> extends false ? SwitchChainError : never) | (errorObject['code'] extends AtomicReadyWalletRejectedUpgradeError['code'] ? AtomicReadyWalletRejectedUpgradeError : never) | (IsNarrowable<errorObject['code'], number> extends false ? AtomicReadyWalletRejectedUpgradeError : never) | (errorObject['code'] extends AtomicityNotSupportedError['code'] ? AtomicityNotSupportedError : never) | (IsNarrowable<errorObject['code'], number> extends false ? AtomicityNotSupportedError : never) | (errorObject['code'] extends BundleTooLargeError['code'] ? BundleTooLargeError : never) | (IsNarrowable<errorObject['code'], number> extends false ? BundleTooLargeError : never) | (errorObject['code'] extends UnknownBundleIdError['code'] ? UnknownBundleIdError : never) | (IsNarrowable<errorObject['code'], number> extends false ? UnknownBundleIdError : never) | (errorObject['code'] extends DuplicateIdError['code'] ? DuplicateIdError : never) | (IsNarrowable<errorObject['code'], number> extends false ? DuplicateIdError : never) | (errorObject['code'] extends UnsupportedChainIdError['code'] ? UnsupportedChainIdError : never) | (IsNarrowable<errorObject['code'], number> extends false ? UnsupportedChainIdError : never) | (errorObject['code'] extends UnsupportedNonOptionalCapabilityError['code'] ? UnsupportedNonOptionalCapabilityError : never) | (IsNarrowable<errorObject['code'], number> extends false ? UnsupportedNonOptionalCapabilityError : never) : RpcResponse.parseError.ReturnType<RpcResponse.ErrorObject>> = IsNever<error> extends true ? RpcResponse.parseError.ReturnType<errorObject> : error;
}
/** Thrown when the provider is undefined. */
export declare class IsUndefinedError extends Errors.BaseError {
    readonly name = "Provider.IsUndefinedError";
    constructor();
}
//# sourceMappingURL=Provider.d.ts.map