import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';
import { DataPublisher } from '@solana/subscribable';
import { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';
import { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';
export type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{
    planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;
    /**
     * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC
     * server.
     *
     * This is useful when the params supplied by the caller need to be transformed before
     * forwarding the message to the server. Use cases for this include applying defaults,
     * forwarding calls to renamed methods, and serializing complex values.
     */
    requestTransformer?: RpcRequestTransformer;
}>;
/**
 * A function that implements a protocol for subscribing and unsubscribing from notifications given
 * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.
 *
 * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}
 */
type RpcSubscriptionsPlanExecutor<TNotification> = (config: Readonly<{
    channel: RpcSubscriptionsChannel<unknown, unknown>;
    request: RpcRequest;
    signal: AbortSignal;
}>) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;
/**
 * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should
 * be issued to the JSON RPC server.
 *
 * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`
 * function that dictates which subscription request will be sent, how the underlying transport will
 * be used, and how the notifications will be transformed.
 *
 * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously
 * returns a {@link DataPublisher}. This gives us the opportunity to:
 *
 * - define the `payload` from the requested method name and parameters before passing it to the
 *   channel.
 * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.
 *   caching or coalescing multiple subscriptions).
 * - transform the notification from the JSON RPC server, in case it does not match the
 *   `TNotification` specified by the
 *   {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted
 *   from the publisher returned.
 */
export type RpcSubscriptionsPlan<TNotification> = Readonly<{
    /**
     * This method may be called with a newly-opened channel or a pre-established channel.
     */
    execute: (config: Readonly<{
        channel: RpcSubscriptionsChannel<unknown, unknown>;
        signal: AbortSignal;
    }>) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;
    /**
     * This request is used to uniquely identify the subscription.
     * It typically comes from the method name and parameters of the subscription call,
     * after potentially being transformed by the RPC Subscriptions API.
     */
    request: RpcRequest;
}>;
/**
 * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps
 * between its input arguments and a
 * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution
 * of a JSON RPC subscription for `TNotifications`.
 */
export type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {
    [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<TRpcSubscriptionMethods[MethodName]>;
};
type RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>> : never;
type RpcSubscriptionsApiMethod = (...args: any) => any;
export interface RpcSubscriptionsApiMethods {
    [methodName: string]: RpcSubscriptionsApiMethod;
}
/**
 * Creates a JavaScript proxy that converts _any_ function call called on it to a
 * {@link RpcSubscriptionsPlan} by creating an `execute` function that:
 *
 * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload
 *   object with the requested `methodName` and `params` properties, optionally transformed by
 *   {@link RpcSubscriptionsApiConfig.requestTransformer}.
 *
 * @example
 * ```ts
 * // For example, given this `RpcSubscriptionsApi`:
 * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({
 *     async planExecutor({ channel, request }) {
 *         await channel.send(request);
 *         return {
 *             ...channel,
 *             on(type, listener, options) {
 *                 if (type !== 'message') {
 *                     return channel.on(type, listener, options);
 *                 }
 *                 return channel.on(
 *                     'message',
 *                     function resultGettingListener(message) {
 *                         listener(message.result);
 *                     },
 *                     options,
 *                 );
 *             }
 *         }
 *     },
 *     requestTransformer: (...rawParams) => rawParams.reverse(),
 * });
 *
 * // ...the following function call:
 * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });
 *
 * // ...will produce a `RpcSubscriptionsPlan` that:
 * // -   Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.
 * // -   Emits the "result" property of each RPC Subscriptions message.
 * ```
 */
export declare function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>;
export {};
//# sourceMappingURL=rpc-subscriptions-api.d.ts.map