@solana/rpc-subscriptions-spec 5.1.0-canary-20251202173352 → 5.1.0-canary-20251203213248
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.browser.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["SolanaError","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN","createAsyncIterableFromDataPublisher","AbortController","demultiplexDataPublisher","createRpcMessage","getSolanaErrorFromJsonRpcError","safeRace","SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID","SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED"],"mappings":"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","file":"index.browser.cjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.browser.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["SolanaError","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN","createAsyncIterableFromDataPublisher","AbortController","demultiplexDataPublisher","createRpcMessage","getSolanaErrorFromJsonRpcError","safeRace","SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID","SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED"],"mappings":";;;;;;;;AA+CO,SAAS,sBACZ,SAAA,EAC6C;AAC7C,EAAA,OAAO,IAAI,KAAA,CAAM,SAAA,CAAU,GAAA,EAAK;AAAA,IAC5B,cAAA,GAAiB;AACb,MAAA,OAAO,KAAA;AAAA,IACX,CAAA;AAAA,IACA,cAAA,GAAiB;AACb,MAAA,OAAO,KAAA;AAAA,IACX,CAAA;AAAA,IACA,GAAA,CAAI,MAAA,EAAQ,CAAA,EAAG,QAAA,EAAU;AACrB,MAAA,IAAI,MAAM,MAAA,EAAQ;AACd,QAAA,OAAO,MAAA;AAAA,MACX;AACA,MAAA,OAAO,YAAa,SAAA,EAAsB;AACtC,QAAA,MAAM,gBAAA,GAAmB,EAAE,QAAA,EAAS;AACpC,QAAA,MAAM,yBAAA,GAA4B,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,kBAAkB,QAAQ,CAAA;AAChF,QAAA,IAAI,CAAC,yBAAA,EAA2B;AAC5B,UAAA,MAAM,IAAIA,mBAAYC,uEAAA,EAAkE;AAAA,YACpF;AAAA,WACH,CAAA;AAAA,QACL;AACA,QAAA,MAAM,gBAAA,GAAmB,yBAAA,CAA0B,GAAG,SAAS,CAAA;AAC/D,QAAA,OAAO,4BAAA,CAA6B,SAAA,CAAU,SAAA,EAAW,gBAAgB,CAAA;AAAA,MAC7E,CAAA;AAAA,IACJ;AAAA,GACH,CAAA;AACL;AAEA,SAAS,4BAAA,CACL,WACA,iBAAA,EAC6C;AAC7C,EAAA,OAAO;AAAA,IACH,MAAM,SAAA,CAAU,EAAE,WAAA,EAAY,EAA+D;AACzF,MAAA,MAAM,0BAAA,GAA6B,MAAM,SAAA,CAAU;AAAA,QAC/C,MAAA,EAAQ,WAAA;AAAA,QACR,GAAG;AAAA,OACN,CAAA;AACD,MAAA,OAAOC,iDAAA,CAAoD;AAAA,QACvD,WAAA;AAAA,QACA,eAAA,EAAiB,cAAA;AAAA,QACjB,aAAA,EAAe,0BAAA;AAAA,QACf,gBAAA,EAAkB;AAAA,OACrB,CAAA;AAAA,IACL;AAAA,GACJ;AACJ;;;ACwCO,SAAS,0BACZ,MAAA,EACgD;AAChD,EAAA,OAAO,IAAI,KAAA,CAAM,EAAC,EAAuD;AAAA,IACrE,cAAA,GAAiB;AACb,MAAA,OAAO,KAAA;AAAA,IACX,CAAA;AAAA,IACA,cAAA,GAAiB;AACb,MAAA,OAAO,KAAA;AAAA,IACX,CAAA;AAAA,IACA,OACO,IAAA,EACL;AACE,MAAA,MAAM,CAAC,CAAA,EAAG,CAAC,CAAA,GAAI,IAAA;AACf,MAAA,MAAM,UAAA,GAAa,EAAE,QAAA,EAAS;AAC9B,MAAA,OAAO,YACA,MAAA,EAK6E;AAChF,QAAA,MAAM,UAAA,GAAa,EAAE,UAAA,EAAY,MAAA,EAAO;AACxC,QAAA,MAAM,UAAU,MAAA,CAAO,kBAAA,GAAqB,MAAA,CAAO,kBAAA,CAAmB,UAAU,CAAA,GAAI,UAAA;AACpF,QAAA,OAAO;AAAA,UACH,QAAQ,UAAA,EAAY;AAChB,YAAA,OAAO,OAAO,YAAA,CAAa,EAAE,GAAG,UAAA,EAAY,SAAS,CAAA;AAAA,UACzD,CAAA;AAAA,UACA;AAAA,SACJ;AAAA,MACJ,CAAA;AAAA,IACJ;AAAA,GACH,CAAA;AACL;;;AC5GO,SAAS,+BAAA,CACZ,SACA,SAAA,EAC6D;AAC7D,EAAA,OAAO,OAAO,MAAA,CAAsE;AAAA,IAChF,GAAG,OAAA;AAAA,IACH,EAAA,CAAG,IAAA,EAAM,UAAA,EAAY,OAAA,EAAS;AAC1B,MAAA,IAAI,SAAS,SAAA,EAAW;AACpB,QAAA,OAAO,OAAA,CAAQ,EAAA;AAAA,UACX,IAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACJ;AAAA,MACJ;AACA,MAAA,OAAO,OAAA,CAAQ,EAAA;AAAA,QACX,SAAA;AAAA,QACA,CAAA,OAAA,KAAY,UAAA,CAAkD,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,QAChF;AAAA,OACJ;AAAA,IACJ;AAAA,GACH,CAAA;AACL;AAWO,SAAS,gCAAA,CACZ,SACA,SAAA,EAC6D;AAC7D,EAAA,OAAO,OAAO,MAAA,CAAsE;AAAA,IAChF,GAAG,OAAA;AAAA,IACH,MAAM,CAAA,OAAA,KAAW,OAAA,CAAQ,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC;AAAA,GACnD,CAAA;AACL;;;ACnGO,IAAMC,IAAkB,UAAA,CAAW,eAAA;ACqC1C,IAAM,wCAAA,uBAA+C,OAAA,EAAyC;AAC9F,SAAS,yCAAA,CAA0C,SAAkB,cAAA,EAA6C;AAC9G,EAAA,OAAO,uCAAA,CAAwC,EAAA,EAAI,OAAA,EAAS,cAAc,CAAA;AAC9E;AACA,SAAS,wBAAA,CAAyB,SAAkB,cAAA,EAA+B;AAC/E,EAAA,uCAAA,CAAwC,CAAA,EAAG,SAAS,cAAc,CAAA;AACtE;AACA,SAAS,6CAA6C,OAAA,EAA0C;AAC5F,EAAA,IAAI,+BAAA,GAAkC,wCAAA,CAAyC,GAAA,CAAI,OAAO,CAAA;AAC1F,EAAA,IAAI,CAAC,+BAAA,EAAiC;AAClC,IAAA,wCAAA,CAAyC,GAAA,CAAI,OAAA,EAAU,+BAAA,GAAkC,EAAG,CAAA;AAAA,EAChG;AACA,EAAA,OAAO,+BAAA;AACX;AACA,SAAS,uCAAA,CACL,MAAA,EACA,OAAA,EACA,cAAA,EACkB;AAClB,EAAA,IAAI,mBAAmB,MAAA,EAAW;AAC9B,IAAA;AAAA,EACJ;AACA,EAAA,MAAM,+BAAA,GAAkC,6CAA6C,OAAO,CAAA;AAC5F,EAAA,IAAI,CAAC,+BAAA,CAAgC,cAAc,CAAA,IAAK,SAAS,CAAA,EAAG;AAChE,IAAA,+BAAA,CAAgC,cAAc,CAAA,GAAI,CAAA;AAAA,EACtD;AACA,EAAA,MAAM,QAAA,GAAW,MAAA,GAAS,+BAAA,CAAgC,cAAc,CAAA;AACxE,EAAA,IAAI,YAAY,CAAA,EAAG;AACf,IAAA,OAAO,gCAAgC,cAAc,CAAA;AAAA,EACzD,CAAA,MAAO;AACH,IAAA,+BAAA,CAAgC,cAAc,CAAA,GAAI,QAAA;AAAA,EACtD;AACA,EAAA,OAAO,QAAA;AACX;AAEA,IAAM,KAAA,uBAAY,OAAA,EAAQ;AAC1B,SAAS,8EAAA,CACL,OAAA,EACA,gBAAA,EACA,mBAAA,EAGD;AACC,EAAA,IAAI,8BAAA,GAAiC,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA;AACtD,EAAA,IAAI,CAAC,8BAAA,EAAgC;AACjC,IAAA,KAAA,CAAM,GAAA,CAAI,OAAA,EAAU,8BAAA,mBAAiC,IAAI,SAAU,CAAA;AAAA,EACvE;AACA,EAAA,MAAM,yBAAyB,mBAAA,IAAuB,OAAA;AACtD,EAAA,IAAI,SAAA,GAAY,8BAAA,CAA+B,GAAA,CAAI,sBAAsB,CAAA;AACzE,EAAA,IAAI,CAAC,SAAA,EAAW;AACZ,IAAA,8BAAA,CAA+B,GAAA;AAAA,MAC3B,sBAAA;AAAA,MACC,SAAA,GAAYC,qCAAA,CAAyB,OAAA,EAAS,SAAA,EAAW,CAAA,UAAA,KAAc;AACpE,QAAA,MAAM,OAAA,GAAU,UAAA;AAChB,QAAA,IAAI,EAAE,YAAY,OAAA,CAAA,EAAU;AACxB,UAAA;AAAA,QACJ;AACA,QAAA,MAAM,uBAAA,GAA0B,sBAC1B,mBAAA,CAAoB,OAAA,CAAQ,OAAO,MAAA,EAAQ,gBAAgB,CAAA,GAC3D,OAAA,CAAQ,MAAA,CAAO,MAAA;AACrB,QAAA,OAAO,CAAC,CAAA,aAAA,EAAgB,OAAA,CAAQ,MAAA,CAAO,YAAY,IAAI,uBAAuB,CAAA;AAAA,MAClF,CAAC;AAAA,KACL;AAAA,EACJ;AACA,EAAA,OAAO,SAAA;AACX;AAcA,eAAsB,gCAAA,CAAgD;AAAA,EAClE,OAAA;AAAA,EACA,mBAAA;AAAA,EACA,MAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACJ,CAAA,EAAoG;AAChG,EAAA,IAAI,cAAA;AACJ,EAAA,OAAA,CAAQ,EAAA;AAAA,IACJ,OAAA;AAAA,IACA,MAAM;AAIF,MAAA,cAAA,GAAiB,MAAA;AACjB,MAAA,wCAAA,CAAyC,OAAO,OAAO,CAAA;AAAA,IAC3D,CAAA;AAAA,IACA,EAAE,MAAA;AAAO,GACb;AAMA,EAAA,MAAM,YAAA,GAAe,IAAI,OAAA,CAAe,CAAC,GAAG,MAAA,KAAW;AACnD,IAAA,SAAS,WAAA,GAA+B;AAOpC,MAAA,IAAI,yCAAA,CAA0C,OAAA,EAAS,cAAc,CAAA,KAAM,CAAA,EAAG;AAC1E,QAAA,MAAM,qBAAqBC,6BAAA,CAAiB;AAAA,UACxC,UAAA,EAAY,qBAAA;AAAA,UACZ,MAAA,EAAQ,CAAC,cAAc;AAAA,SAC1B,CAAA;AACD,QAAA,cAAA,GAAiB,MAAA;AACjB,QAAA,OAAA,CAAQ,IAAA,CAAK,kBAAkB,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,QAAC,CAAC,CAAA;AAAA,MACnD;AAEA,MAAA,MAAA,CAAO,KAAK,MAAM,CAAA;AAAA,IACtB;AACA,IAAA,IAAI,OAAO,OAAA,EAAS;AAChB,MAAA,WAAA,CAAY,KAAK,MAAM,CAAA;AAAA,IAC3B,CAAA,MAAO;AACH,MAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAAA,IAChD;AAAA,EACJ,CAAC,CAAA;AAKD,EAAA,MAAM,gBAAA,GAAmBA,8BAAiB,gBAAgB,CAAA;AAC1D,EAAA,MAAM,OAAA,CAAQ,KAAK,gBAAgB,CAAA;AAKnC,EAAA,MAAM,qBAAA,GAAwB,IAAI,OAAA,CAA2B,CAAC,SAAS,MAAA,KAAW;AAC9E,IAAA,MAAM,eAAA,GAAkB,IAAI,CAAA,EAAgB;AAC5C,IAAA,MAAA,CAAO,iBAAiB,OAAA,EAAS,eAAA,CAAgB,KAAA,CAAM,IAAA,CAAK,eAAe,CAAC,CAAA;AAC5E,IAAA,MAAM,OAAA,GAAU,EAAE,MAAA,EAAQ,eAAA,CAAgB,MAAA,EAAO;AACjD,IAAA,OAAA,CAAQ,EAAA;AAAA,MACJ,OAAA;AAAA,MACA,CAAA,GAAA,KAAO;AACH,QAAA,eAAA,CAAgB,KAAA,EAAM;AACtB,QAAA,MAAA,CAAO,GAAG,CAAA;AAAA,MACd,CAAA;AAAA,MACA;AAAA,KACJ;AACA,IAAA,OAAA,CAAQ,EAAA;AAAA,MACJ,SAAA;AAAA,MACA,CAAA,OAAA,KAAW;AACP,QAAA,IAAI,OAAA,IAAW,OAAO,OAAA,KAAY,QAAA,IAAY,QAAQ,OAAA,IAAW,OAAA,CAAQ,EAAA,KAAO,gBAAA,CAAiB,EAAA,EAAI;AACjG,UAAA,eAAA,CAAgB,KAAA,EAAM;AACtB,UAAA,IAAI,WAAW,OAAA,EAAS;AACpB,YAAA,MAAA,CAAOC,qCAAA,CAA+B,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,UACxD,CAAA,MAAO;AACH,YAAA,OAAA,CAAQ,QAAQ,MAAM,CAAA;AAAA,UAC1B;AAAA,QACJ;AAAA,MACJ,CAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ,CAAC,CAAA;AACD,EAAA,cAAA,GAAiB,MAAMC,iBAAA,CAAS,CAAC,YAAA,EAAc,qBAAqB,CAAC,CAAA;AACrE,EAAA,IAAI,kBAAkB,IAAA,EAAM;AACxB,IAAA,MAAM,IAAIP,mBAAYQ,uEAAgE,CAAA;AAAA,EAC1F;AACA,EAAA,wBAAA,CAAyB,SAAS,cAAc,CAAA;AAKhD,EAAA,MAAM,qBAAA,GAAwB,8EAAA;AAAA,IAC1B,OAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACJ;AACA,EAAA,MAAM,eAAA,GAAkB,gBAAgB,cAAc,CAAA,CAAA;AACtD,EAAA,OAAO;AAAA,IACH,EAAA,CAAG,IAAA,EAAM,QAAA,EAAU,OAAA,EAAS;AACxB,MAAA,QAAQ,IAAA;AAAM,QACV,KAAK,cAAA;AACD,UAAA,OAAO,qBAAA,CAAsB,EAAA;AAAA,YACzB,eAAA;AAAA,YACA,QAAA;AAAA,YACA;AAAA,WACJ;AAAA,QACJ,KAAK,OAAA;AACD,UAAA,OAAO,OAAA,CAAQ,EAAA;AAAA,YACX,OAAA;AAAA,YACA,QAAA;AAAA,YACA;AAAA,WACJ;AAAA,QACJ;AACI,UAAA,MAAM,IAAIR,mBAAYS,8EAAA,EAAyE;AAAA,YAC3F,WAAA,EAAa,IAAA;AAAA,YACb,qBAAA,EAAuB,CAAC,cAAA,EAAgB,OAAO;AAAA,WAClD,CAAA;AAAA;AACT,IACJ;AAAA,GACJ;AACJ","file":"index.browser.cjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.browser.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["AbortController","SolanaError"],"mappings":";;;;;;AA+CO,SAAS,sBACZ,SAC6C,EAAA;AAC7C,EAAO,OAAA,IAAI,KAAM,CAAA,SAAA,CAAU,GAAK,EAAA;AAAA,IAC5B,cAAiB,GAAA;AACb,MAAO,OAAA,KAAA;AAAA,KACX;AAAA,IACA,cAAiB,GAAA;AACb,MAAO,OAAA,KAAA;AAAA,KACX;AAAA,IACA,GAAA,CAAI,MAAQ,EAAA,CAAA,EAAG,QAAU,EAAA;AACrB,MAAA,IAAI,MAAM,MAAQ,EAAA;AACd,QAAO,OAAA,MAAA;AAAA;AAEX,MAAA,OAAO,YAAa,SAAsB,EAAA;AACtC,QAAM,MAAA,gBAAA,GAAmB,EAAE,QAAS,EAAA;AACpC,QAAA,MAAM,yBAA4B,GAAA,OAAA,CAAQ,GAAI,CAAA,MAAA,EAAQ,kBAAkB,QAAQ,CAAA;AAChF,QAAA,IAAI,CAAC,yBAA2B,EAAA;AAC5B,UAAM,MAAA,IAAI,YAAY,gEAAkE,EAAA;AAAA,YACpF;AAAA,WACH,CAAA;AAAA;AAEL,QAAM,MAAA,gBAAA,GAAmB,yBAA0B,CAAA,GAAG,SAAS,CAAA;AAC/D,QAAO,OAAA,4BAAA,CAA6B,SAAU,CAAA,SAAA,EAAW,gBAAgB,CAAA;AAAA,OAC7E;AAAA;AACJ,GACH,CAAA;AACL;AAEA,SAAS,4BAAA,CACL,WACA,iBAC6C,EAAA;AAC7C,EAAO,OAAA;AAAA,IACH,MAAM,SAAA,CAAU,EAAE,WAAA,EAA2E,EAAA;AACzF,MAAM,MAAA,0BAAA,GAA6B,MAAM,SAAU,CAAA;AAAA,QAC/C,MAAQ,EAAA,WAAA;AAAA,QACR,GAAG;AAAA,OACN,CAAA;AACD,MAAA,OAAO,oCAAoD,CAAA;AAAA,QACvD,WAAA;AAAA,QACA,eAAiB,EAAA,cAAA;AAAA,QACjB,aAAe,EAAA,0BAAA;AAAA,QACf,gBAAkB,EAAA;AAAA,OACrB,CAAA;AAAA;AACL,GACJ;AACJ;;;ACwCO,SAAS,0BACZ,MACgD,EAAA;AAChD,EAAO,OAAA,IAAI,KAAM,CAAA,EAAwD,EAAA;AAAA,IACrE,cAAiB,GAAA;AACb,MAAO,OAAA,KAAA;AAAA,KACX;AAAA,IACA,cAAiB,GAAA;AACb,MAAO,OAAA,KAAA;AAAA,KACX;AAAA,IACA,OACO,IACL,EAAA;AACE,MAAM,MAAA,CAAC,CAAG,EAAA,CAAC,CAAI,GAAA,IAAA;AACf,MAAM,MAAA,UAAA,GAAa,EAAE,QAAS,EAAA;AAC9B,MAAA,OAAO,YACA,MAK6E,EAAA;AAChF,QAAM,MAAA,UAAA,GAAa,EAAE,UAAA,EAAY,MAAO,EAAA;AACxC,QAAA,MAAM,UAAU,MAAO,CAAA,kBAAA,GAAqB,MAAO,CAAA,kBAAA,CAAmB,UAAU,CAAI,GAAA,UAAA;AACpF,QAAO,OAAA;AAAA,UACH,QAAQ,UAAY,EAAA;AAChB,YAAA,OAAO,OAAO,YAAa,CAAA,EAAE,GAAG,UAAA,EAAY,SAAS,CAAA;AAAA,WACzD;AAAA,UACA;AAAA,SACJ;AAAA,OACJ;AAAA;AACJ,GACH,CAAA;AACL;;;AC5GO,SAAS,+BAAA,CACZ,SACA,SAC6D,EAAA;AAC7D,EAAA,OAAO,OAAO,MAAsE,CAAA;AAAA,IAChF,GAAG,OAAA;AAAA,IACH,EAAA,CAAG,IAAM,EAAA,UAAA,EAAY,OAAS,EAAA;AAC1B,MAAA,IAAI,SAAS,SAAW,EAAA;AACpB,QAAA,OAAO,OAAQ,CAAA,EAAA;AAAA,UACX,IAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACJ;AAAA;AAEJ,MAAA,OAAO,OAAQ,CAAA,EAAA;AAAA,QACX,SAAA;AAAA,QACA,CAAY,OAAA,KAAA,UAAA,CAAkD,SAAU,CAAA,OAAO,CAAC,CAAA;AAAA,QAChF;AAAA,OACJ;AAAA;AACJ,GACH,CAAA;AACL;AAWO,SAAS,gCAAA,CACZ,SACA,SAC6D,EAAA;AAC7D,EAAA,OAAO,OAAO,MAAsE,CAAA;AAAA,IAChF,GAAG,OAAA;AAAA,IACH,MAAM,CAAW,OAAA,KAAA,OAAA,CAAQ,IAAK,CAAA,SAAA,CAAU,OAAO,CAAC;AAAA,GACnD,CAAA;AACL;;;ACnGO,IAAMA,IAAkB,UAAW,CAAA,eAAA;ACqC1C,IAAM,wCAAA,uBAA+C,OAAyC,EAAA;AAC9F,SAAS,yCAAA,CAA0C,SAAkB,cAA6C,EAAA;AAC9G,EAAO,OAAA,uCAAA,CAAwC,EAAI,EAAA,OAAA,EAAS,cAAc,CAAA;AAC9E;AACA,SAAS,wBAAA,CAAyB,SAAkB,cAA+B,EAAA;AAC/E,EAAwC,uCAAA,CAAA,CAAA,EAAG,SAAS,cAAc,CAAA;AACtE;AACA,SAAS,6CAA6C,OAA0C,EAAA;AAC5F,EAAI,IAAA,+BAAA,GAAkC,wCAAyC,CAAA,GAAA,CAAI,OAAO,CAAA;AAC1F,EAAA,IAAI,CAAC,+BAAiC,EAAA;AAClC,IAAA,wCAAA,CAAyC,GAAI,CAAA,OAAA,EAAU,+BAAkC,GAAA,EAAG,CAAA;AAAA;AAEhG,EAAO,OAAA,+BAAA;AACX;AACA,SAAS,uCAAA,CACL,MACA,EAAA,OAAA,EACA,cACkB,EAAA;AAClB,EAAA,IAAI,mBAAmB,MAAW,EAAA;AAC9B,IAAA;AAAA;AAEJ,EAAM,MAAA,+BAAA,GAAkC,6CAA6C,OAAO,CAAA;AAC5F,EAAA,IAAI,CAAC,+BAAA,CAAgC,cAAc,CAAA,IAAK,SAAS,CAAG,EAAA;AAChE,IAAA,+BAAA,CAAgC,cAAc,CAAI,GAAA,CAAA;AAAA;AAEtD,EAAM,MAAA,QAAA,GAAW,MAAS,GAAA,+BAAA,CAAgC,cAAc,CAAA;AACxE,EAAA,IAAI,YAAY,CAAG,EAAA;AACf,IAAA,OAAO,gCAAgC,cAAc,CAAA;AAAA,GAClD,MAAA;AACH,IAAA,+BAAA,CAAgC,cAAc,CAAI,GAAA,QAAA;AAAA;AAEtD,EAAO,OAAA,QAAA;AACX;AAEA,IAAM,KAAA,uBAAY,OAAQ,EAAA;AAC1B,SAAS,8EAAA,CACL,OACA,EAAA,gBAAA,EACA,mBAGD,EAAA;AACC,EAAI,IAAA,8BAAA,GAAiC,KAAM,CAAA,GAAA,CAAI,OAAO,CAAA;AACtD,EAAA,IAAI,CAAC,8BAAgC,EAAA;AACjC,IAAA,KAAA,CAAM,GAAI,CAAA,OAAA,EAAU,8BAAiC,mBAAA,IAAI,SAAU,CAAA;AAAA;AAEvE,EAAA,MAAM,yBAAyB,mBAAuB,IAAA,OAAA;AACtD,EAAI,IAAA,SAAA,GAAY,8BAA+B,CAAA,GAAA,CAAI,sBAAsB,CAAA;AACzE,EAAA,IAAI,CAAC,SAAW,EAAA;AACZ,IAA+B,8BAAA,CAAA,GAAA;AAAA,MAC3B,sBAAA;AAAA,MACC,SAAY,GAAA,wBAAA,CAAyB,OAAS,EAAA,SAAA,EAAW,CAAc,UAAA,KAAA;AACpE,QAAA,MAAM,OAAU,GAAA,UAAA;AAChB,QAAI,IAAA,EAAE,YAAY,OAAU,CAAA,EAAA;AACxB,UAAA;AAAA;AAEJ,QAAM,MAAA,uBAAA,GAA0B,sBAC1B,mBAAoB,CAAA,OAAA,CAAQ,OAAO,MAAQ,EAAA,gBAAgB,CAC3D,GAAA,OAAA,CAAQ,MAAO,CAAA,MAAA;AACrB,QAAA,OAAO,CAAC,CAAgB,aAAA,EAAA,OAAA,CAAQ,MAAO,CAAA,YAAY,IAAI,uBAAuB,CAAA;AAAA,OACjF;AAAA,KACL;AAAA;AAEJ,EAAO,OAAA,SAAA;AACX;AAcA,eAAsB,gCAAgD,CAAA;AAAA,EAClE,OAAA;AAAA,EACA,mBAAA;AAAA,EACA,MAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACJ,CAAoG,EAAA;AAChG,EAAI,IAAA,cAAA;AACJ,EAAQ,OAAA,CAAA,EAAA;AAAA,IACJ,OAAA;AAAA,IACA,MAAM;AAIF,MAAiB,cAAA,GAAA,MAAA;AACjB,MAAA,wCAAA,CAAyC,OAAO,OAAO,CAAA;AAAA,KAC3D;AAAA,IACA,EAAE,MAAO;AAAA,GACb;AAMA,EAAA,MAAM,YAAe,GAAA,IAAI,OAAe,CAAA,CAAC,GAAG,MAAW,KAAA;AACnD,IAAA,SAAS,WAA+B,GAAA;AAOpC,MAAA,IAAI,yCAA0C,CAAA,OAAA,EAAS,cAAc,CAAA,KAAM,CAAG,EAAA;AAC1E,QAAA,MAAM,qBAAqB,gBAAiB,CAAA;AAAA,UACxC,UAAY,EAAA,qBAAA;AAAA,UACZ,MAAA,EAAQ,CAAC,cAAc;AAAA,SAC1B,CAAA;AACD,QAAiB,cAAA,GAAA,MAAA;AACjB,QAAA,OAAA,CAAQ,IAAK,CAAA,kBAAkB,CAAE,CAAA,KAAA,CAAM,MAAM;AAAA,SAAE,CAAA;AAAA;AAGnD,MAAA,MAAA,CAAO,KAAK,MAAM,CAAA;AAAA;AAEtB,IAAA,IAAI,OAAO,OAAS,EAAA;AAChB,MAAA,WAAA,CAAY,KAAK,MAAM,CAAA;AAAA,KACpB,MAAA;AACH,MAAO,MAAA,CAAA,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAAA;AAChD,GACH,CAAA;AAKD,EAAM,MAAA,gBAAA,GAAmB,iBAAiB,gBAAgB,CAAA;AAC1D,EAAM,MAAA,OAAA,CAAQ,KAAK,gBAAgB,CAAA;AAKnC,EAAA,MAAM,qBAAwB,GAAA,IAAI,OAA2B,CAAA,CAAC,SAAS,MAAW,KAAA;AAC9E,IAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,IAAA,MAAA,CAAO,iBAAiB,OAAS,EAAA,eAAA,CAAgB,KAAM,CAAA,IAAA,CAAK,eAAe,CAAC,CAAA;AAC5E,IAAA,MAAM,OAAU,GAAA,EAAE,MAAQ,EAAA,eAAA,CAAgB,MAAO,EAAA;AACjD,IAAQ,OAAA,CAAA,EAAA;AAAA,MACJ,OAAA;AAAA,MACA,CAAO,GAAA,KAAA;AACH,QAAA,eAAA,CAAgB,KAAM,EAAA;AACtB,QAAA,MAAA,CAAO,GAAG,CAAA;AAAA,OACd;AAAA,MACA;AAAA,KACJ;AACA,IAAQ,OAAA,CAAA,EAAA;AAAA,MACJ,SAAA;AAAA,MACA,CAAW,OAAA,KAAA;AACP,QAAI,IAAA,OAAA,IAAW,OAAO,OAAY,KAAA,QAAA,IAAY,QAAQ,OAAW,IAAA,OAAA,CAAQ,EAAO,KAAA,gBAAA,CAAiB,EAAI,EAAA;AACjG,UAAA,eAAA,CAAgB,KAAM,EAAA;AACtB,UAAA,IAAI,WAAW,OAAS,EAAA;AACpB,YAAO,MAAA,CAAA,8BAAA,CAA+B,OAAQ,CAAA,KAAK,CAAC,CAAA;AAAA,WACjD,MAAA;AACH,YAAA,OAAA,CAAQ,QAAQ,MAAM,CAAA;AAAA;AAC1B;AACJ,OACJ;AAAA,MACA;AAAA,KACJ;AAAA,GACH,CAAA;AACD,EAAA,cAAA,GAAiB,MAAM,QAAA,CAAS,CAAC,YAAA,EAAc,qBAAqB,CAAC,CAAA;AACrE,EAAA,IAAI,kBAAkB,IAAM,EAAA;AACxB,IAAM,MAAA,IAAIC,YAAY,gEAAgE,CAAA;AAAA;AAE1F,EAAA,wBAAA,CAAyB,SAAS,cAAc,CAAA;AAKhD,EAAA,MAAM,qBAAwB,GAAA,8EAAA;AAAA,IAC1B,OAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACJ;AACA,EAAM,MAAA,eAAA,GAAkB,gBAAgB,cAAc,CAAA,CAAA;AACtD,EAAO,OAAA;AAAA,IACH,EAAA,CAAG,IAAM,EAAA,QAAA,EAAU,OAAS,EAAA;AACxB,MAAA,QAAQ,IAAM;AAAA,QACV,KAAK,cAAA;AACD,UAAA,OAAO,qBAAsB,CAAA,EAAA;AAAA,YACzB,eAAA;AAAA,YACA,QAAA;AAAA,YACA;AAAA,WACJ;AAAA,QACJ,KAAK,OAAA;AACD,UAAA,OAAO,OAAQ,CAAA,EAAA;AAAA,YACX,OAAA;AAAA,YACA,QAAA;AAAA,YACA;AAAA,WACJ;AAAA,QACJ;AACI,UAAM,MAAA,IAAIA,YAAY,uEAAyE,EAAA;AAAA,YAC3F,WAAa,EAAA,IAAA;AAAA,YACb,qBAAA,EAAuB,CAAC,cAAA,EAAgB,OAAO;AAAA,WAClD,CAAA;AAAA;AACT;AACJ,GACJ;AACJ","file":"index.browser.mjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.browser.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["AbortController","SolanaError"],"mappings":"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","file":"index.browser.mjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.browser.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["AbortController","SolanaError"],"mappings":"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","file":"index.native.mjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.browser.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["AbortController","SolanaError"],"mappings":"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","file":"index.native.mjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
package/dist/index.node.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.node.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["SolanaError","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN","createAsyncIterableFromDataPublisher","AbortController","args","setMaxListeners","demultiplexDataPublisher","createRpcMessage","getSolanaErrorFromJsonRpcError","safeRace","SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID","SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED"],"mappings":"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","file":"index.node.cjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.node.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["SolanaError","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN","createAsyncIterableFromDataPublisher","AbortController","args","setMaxListeners","demultiplexDataPublisher","createRpcMessage","getSolanaErrorFromJsonRpcError","safeRace","SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID","SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED"],"mappings":"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","file":"index.node.cjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
package/dist/index.node.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.node.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["AbortController","args","setMaxListeners","SolanaError"],"mappings":"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","file":"index.node.mjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/rpc-subscriptions.ts","../src/rpc-subscriptions-api.ts","../src/rpc-subscriptions-channel.ts","../../event-target-impl/src/index.node.ts","../src/rpc-subscriptions-pubsub-plan.ts"],"names":["AbortController","args","setMaxListeners","SolanaError"],"mappings":"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","file":"index.node.mjs","sourcesContent":["import { SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, SolanaError } from '@solana/errors';\nimport { Callable, Flatten, OverloadImplementations, UnionToIntersection } from '@solana/rpc-spec-types';\nimport { createAsyncIterableFromDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsApi, RpcSubscriptionsPlan } from './rpc-subscriptions-api';\nimport { PendingRpcSubscriptionsRequest, RpcSubscribeOptions } from './rpc-subscriptions-request';\nimport { RpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsConfig<TRpcMethods> = Readonly<{\n api: RpcSubscriptionsApi<TRpcMethods>;\n transport: RpcSubscriptionsTransport;\n}>;\n\n/**\n * An object that exposes all of the functions described by `TRpcSubscriptionsMethods`.\n *\n * Calling each method returns a\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} where\n * `TNotification` is that method's notification type.\n */\nexport type RpcSubscriptions<TRpcSubscriptionsMethods> = {\n [TMethodName in keyof TRpcSubscriptionsMethods]: PendingRpcSubscriptionsRequestBuilder<\n OverloadImplementations<TRpcSubscriptionsMethods, TMethodName>\n >;\n};\n\ntype PendingRpcSubscriptionsRequestBuilder<TSubscriptionMethodImplementations> = UnionToIntersection<\n Flatten<{\n [P in keyof TSubscriptionMethodImplementations]: PendingRpcSubscriptionsRequestReturnTypeMapper<\n TSubscriptionMethodImplementations[P]\n >;\n }>\n>;\n\ntype PendingRpcSubscriptionsRequestReturnTypeMapper<TSubscriptionMethodImplementation> =\n // Check that this property of the TRpcSubscriptionMethods interface is, in fact, a function.\n TSubscriptionMethodImplementation extends Callable\n ? (\n ...args: Parameters<TSubscriptionMethodImplementation>\n ) => PendingRpcSubscriptionsRequest<ReturnType<TSubscriptionMethodImplementation>>\n : never;\n\n/**\n * Creates a {@link RpcSubscriptions} instance given a\n * {@link RpcSubscriptionsApi | RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>} and a\n * {@link RpcSubscriptionsTransport} capable of fulfilling them.\n */\nexport function createSubscriptionRpc<TRpcSubscriptionsApiMethods>(\n rpcConfig: RpcSubscriptionsConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptions<TRpcSubscriptionsApiMethods> {\n return new Proxy(rpcConfig.api, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get(target, p, receiver) {\n if (p === 'then') {\n return undefined;\n }\n return function (...rawParams: unknown[]) {\n const notificationName = p.toString();\n const createRpcSubscriptionPlan = Reflect.get(target, notificationName, receiver);\n if (!createRpcSubscriptionPlan) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CANNOT_CREATE_SUBSCRIPTION_PLAN, {\n notificationName,\n });\n }\n const subscriptionPlan = createRpcSubscriptionPlan(...rawParams);\n return createPendingRpcSubscription(rpcConfig.transport, subscriptionPlan);\n };\n },\n }) as RpcSubscriptions<TRpcSubscriptionsApiMethods>;\n}\n\nfunction createPendingRpcSubscription<TNotification>(\n transport: RpcSubscriptionsTransport,\n subscriptionsPlan: RpcSubscriptionsPlan<TNotification>,\n): PendingRpcSubscriptionsRequest<TNotification> {\n return {\n async subscribe({ abortSignal }: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>> {\n const notificationsDataPublisher = await transport({\n signal: abortSignal,\n ...subscriptionsPlan,\n });\n return createAsyncIterableFromDataPublisher<TNotification>({\n abortSignal,\n dataChannelName: 'notification',\n dataPublisher: notificationsDataPublisher,\n errorChannelName: 'error',\n });\n },\n };\n}\n","import { Callable, RpcRequest, RpcRequestTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsTransportDataEvents } from './rpc-subscriptions-transport';\n\nexport type RpcSubscriptionsApiConfig<TApiMethods extends RpcSubscriptionsApiMethods> = Readonly<{\n planExecutor: RpcSubscriptionsPlanExecutor<ReturnType<TApiMethods[keyof TApiMethods]>>;\n /**\n * An optional function that transforms the {@link RpcRequest} before it is sent to the JSON RPC\n * server.\n *\n * This is useful when the params supplied by the caller need to be transformed before\n * forwarding the message to the server. Use cases for this include applying defaults,\n * forwarding calls to renamed methods, and serializing complex values.\n */\n requestTransformer?: RpcRequestTransformer;\n}>;\n\n/**\n * A function that implements a protocol for subscribing and unsubscribing from notifications given\n * a {@link RpcSubscriptionsChannel}, a {@link RpcRequest}, and an `AbortSignal`.\n *\n * @returns A {@link DataPublisher} that emits {@link RpcSubscriptionsTransportDataEvents}\n */\ntype RpcSubscriptionsPlanExecutor<TNotification> = (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n request: RpcRequest;\n signal: AbortSignal;\n }>,\n) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n\n/**\n * This type allows an {@link RpcSubscriptionsApi} to describe how a particular subscription should\n * be issued to the JSON RPC server.\n *\n * Given a function that was called on a {@link RpcSubscriptions}, this object exposes an `execute`\n * function that dictates which subscription request will be sent, how the underlying transport will\n * be used, and how the notifications will be transformed.\n *\n * This function accepts a {@link RpcSubscriptionsChannel} and an `AbortSignal` and asynchronously\n * returns a {@link DataPublisher}. This gives us the opportunity to:\n *\n * - define the `payload` from the requested method name and parameters before passing it to the\n * channel.\n * - call the underlying channel zero, one or multiple times depending on the use-case (e.g.\n * caching or coalescing multiple subscriptions).\n * - transform the notification from the JSON RPC server, in case it does not match the\n * `TNotification` specified by the\n * {@link PendingRpcSubscriptionsRequest | PendingRpcSubscriptionsRequest<TNotification>} emitted\n * from the publisher returned.\n */\nexport type RpcSubscriptionsPlan<TNotification> = Readonly<{\n /**\n * This method may be called with a newly-opened channel or a pre-established channel.\n */\n execute: (\n config: Readonly<{\n channel: RpcSubscriptionsChannel<unknown, unknown>;\n signal: AbortSignal;\n }>,\n ) => Promise<DataPublisher<RpcSubscriptionsTransportDataEvents<TNotification>>>;\n /**\n * This request is used to uniquely identify the subscription.\n * It typically comes from the method name and parameters of the subscription call,\n * after potentially being transformed by the RPC Subscriptions API.\n */\n request: RpcRequest;\n}>;\n\n/**\n * For each of `TRpcSubscriptionsMethods`, this object exposes a method with the same name that maps\n * between its input arguments and a\n * {@link RpcSubscriptionsPlan | RpcSubscriptionsPlan<TNotification>} that implements the execution\n * of a JSON RPC subscription for `TNotifications`.\n */\nexport type RpcSubscriptionsApi<TRpcSubscriptionMethods> = {\n [MethodName in keyof TRpcSubscriptionMethods]: RpcSubscriptionsReturnTypeMapper<\n TRpcSubscriptionMethods[MethodName]\n >;\n};\n\ntype RpcSubscriptionsReturnTypeMapper<TRpcMethod> = TRpcMethod extends Callable\n ? (...rawParams: unknown[]) => RpcSubscriptionsPlan<ReturnType<TRpcMethod>>\n : never;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RpcSubscriptionsApiMethod = (...args: any) => any;\nexport interface RpcSubscriptionsApiMethods {\n [methodName: string]: RpcSubscriptionsApiMethod;\n}\n\n/**\n * Creates a JavaScript proxy that converts _any_ function call called on it to a\n * {@link RpcSubscriptionsPlan} by creating an `execute` function that:\n *\n * - calls the supplied {@link RpcSubscriptionsApiConfig.planExecutor} with a JSON RPC v2 payload\n * object with the requested `methodName` and `params` properties, optionally transformed by\n * {@link RpcSubscriptionsApiConfig.requestTransformer}.\n *\n * @example\n * ```ts\n * // For example, given this `RpcSubscriptionsApi`:\n * const rpcSubscriptionsApi = createJsonRpcSubscriptionsApi({\n * async planExecutor({ channel, request }) {\n * await channel.send(request);\n * return {\n * ...channel,\n * on(type, listener, options) {\n * if (type !== 'message') {\n * return channel.on(type, listener, options);\n * }\n * return channel.on(\n * 'message',\n * function resultGettingListener(message) {\n * listener(message.result);\n * },\n * options,\n * );\n * }\n * }\n * },\n * requestTransformer: (...rawParams) => rawParams.reverse(),\n * });\n *\n * // ...the following function call:\n * rpcSubscriptionsApi.foo('bar', { baz: 'bat' });\n *\n * // ...will produce a `RpcSubscriptionsPlan` that:\n * // - Uses the following payload: { id: 1, jsonrpc: '2.0', method: 'foo', params: [{ baz: 'bat' }, 'bar'] }.\n * // - Emits the \"result\" property of each RPC Subscriptions message.\n * ```\n */\nexport function createRpcSubscriptionsApi<TRpcSubscriptionsApiMethods extends RpcSubscriptionsApiMethods>(\n config: RpcSubscriptionsApiConfig<TRpcSubscriptionsApiMethods>,\n): RpcSubscriptionsApi<TRpcSubscriptionsApiMethods> {\n return new Proxy({} as RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>, {\n defineProperty() {\n return false;\n },\n deleteProperty() {\n return false;\n },\n get<TNotificationName extends keyof RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>(\n ...args: Parameters<NonNullable<ProxyHandler<RpcSubscriptionsApi<TRpcSubscriptionsApiMethods>>['get']>>\n ) {\n const [_, p] = args;\n const methodName = p.toString() as keyof TRpcSubscriptionsApiMethods as string;\n return function (\n ...params: Parameters<\n TRpcSubscriptionsApiMethods[TNotificationName] extends CallableFunction\n ? TRpcSubscriptionsApiMethods[TNotificationName]\n : never\n >\n ): RpcSubscriptionsPlan<ReturnType<TRpcSubscriptionsApiMethods[TNotificationName]>> {\n const rawRequest = { methodName, params };\n const request = config.requestTransformer ? config.requestTransformer(rawRequest) : rawRequest;\n return {\n execute(planConfig) {\n return config.planExecutor({ ...planConfig, request });\n },\n request,\n };\n };\n },\n });\n}\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype RpcSubscriptionsChannelSolanaErrorCode =\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED\n | typeof SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT;\n\nexport type RpcSubscriptionChannelEvents<TInboundMessage> = {\n /**\n * Fires when the channel closes unexpectedly.\n * @eventProperty\n */\n error: SolanaError<RpcSubscriptionsChannelSolanaErrorCode>;\n /**\n * Fires on every message received from the remote end.\n * @eventProperty\n */\n message: TInboundMessage;\n};\n\n/**\n * A {@link DataPublisher} on which you can subscribe to events of type\n * {@link RpcSubscriptionChannelEvents | RpcSubscriptionChannelEvents<TInboundMessage>}.\n * Additionally, you can use this object to send messages of type `TOutboundMessage` back to the\n * remote end by calling its {@link RpcSubscriptionsChannel.send | `send(message)`} method.\n */\nexport interface RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>\n extends DataPublisher<RpcSubscriptionChannelEvents<TInboundMessage>> {\n send(message: TOutboundMessage): Promise<void>;\n}\n\n/**\n * A channel creator is a function that accepts an `AbortSignal`, returns a new\n * {@link RpcSubscriptionsChannel}, and tears down the channel when the abort signal fires.\n */\nexport type RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage> = (\n config: Readonly<{\n abortSignal: AbortSignal;\n }>,\n) => Promise<RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>>;\n\n/**\n * Given a channel with inbound messages of type `T` and a function of type `T => U`, returns a new\n * channel with inbound messages of type `U`.\n *\n * Note that this only affects messages of type `\"message\"` and thus, does not affect incoming error\n * messages.\n *\n * @example Parsing incoming JSON messages\n * ```ts\n * const transformedChannel = transformChannelInboundMessages(channel, JSON.parse);\n * ```\n */\nexport function transformChannelInboundMessages<TOutboundMessage, TNewInboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TInboundMessage) => TNewInboundMessage,\n): RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TOutboundMessage, TNewInboundMessage>>({\n ...channel,\n on(type, subscriber, options) {\n if (type !== 'message') {\n return channel.on(\n type,\n subscriber as (data: RpcSubscriptionChannelEvents<TInboundMessage>[typeof type]) => void,\n options,\n );\n }\n return channel.on(\n 'message',\n message => (subscriber as (data: TNewInboundMessage) => void)(transform(message)),\n options,\n );\n },\n });\n}\n\n/**\n * Given a channel with outbound messages of type `T` and a function of type `U => T`, returns a new\n * channel with outbound messages of type `U`.\n *\n * @example Stringifying JSON messages before sending them over the wire\n * ```ts\n * const transformedChannel = transformChannelOutboundMessages(channel, JSON.stringify);\n * ```\n */\nexport function transformChannelOutboundMessages<TNewOutboundMessage, TOutboundMessage, TInboundMessage>(\n channel: RpcSubscriptionsChannel<TOutboundMessage, TInboundMessage>,\n transform: (message: TNewOutboundMessage) => TOutboundMessage,\n): RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage> {\n return Object.freeze<RpcSubscriptionsChannel<TNewOutboundMessage, TInboundMessage>>({\n ...channel,\n send: message => channel.send(transform(message)),\n });\n}\n","import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","import {\n getSolanaErrorFromJsonRpcError,\n SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID,\n SolanaError,\n} from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport { createRpcMessage, RpcRequest, RpcResponseData, RpcResponseTransformer } from '@solana/rpc-spec-types';\nimport { DataPublisher } from '@solana/subscribable';\nimport { demultiplexDataPublisher } from '@solana/subscribable';\n\nimport { RpcSubscriptionChannelEvents } from './rpc-subscriptions-channel';\nimport { RpcSubscriptionsChannel } from './rpc-subscriptions-channel';\n\ntype Config<TNotification> = Readonly<{\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification> | RpcResponseData<RpcSubscriptionId>>;\n responseTransformer?: RpcResponseTransformer;\n signal: AbortSignal;\n subscribeRequest: RpcRequest;\n unsubscribeMethodName: string;\n}>;\n\ntype RpcNotification<TNotification> = Readonly<{\n method: string;\n params: Readonly<{\n result: TNotification;\n subscription: number;\n }>;\n}>;\n\ntype RpcSubscriptionId = number;\n\ntype RpcSubscriptionNotificationEvents<TNotification> = Omit<RpcSubscriptionChannelEvents<TNotification>, 'message'> & {\n notification: TNotification;\n};\n\nconst subscriberCountBySubscriptionIdByChannel = new WeakMap<WeakKey, Record<number, number>>();\nfunction decrementSubscriberCountAndReturnNewCount(channel: WeakKey, subscriptionId?: number): number | undefined {\n return augmentSubscriberCountAndReturnNewCount(-1, channel, subscriptionId);\n}\nfunction incrementSubscriberCount(channel: WeakKey, subscriptionId?: number): void {\n augmentSubscriberCountAndReturnNewCount(1, channel, subscriptionId);\n}\nfunction getSubscriberCountBySubscriptionIdForChannel(channel: WeakKey): Record<number, number> {\n let subscriberCountBySubscriptionId = subscriberCountBySubscriptionIdByChannel.get(channel);\n if (!subscriberCountBySubscriptionId) {\n subscriberCountBySubscriptionIdByChannel.set(channel, (subscriberCountBySubscriptionId = {}));\n }\n return subscriberCountBySubscriptionId;\n}\nfunction augmentSubscriberCountAndReturnNewCount(\n amount: -1 | 1,\n channel: WeakKey,\n subscriptionId?: number,\n): number | undefined {\n if (subscriptionId === undefined) {\n return;\n }\n const subscriberCountBySubscriptionId = getSubscriberCountBySubscriptionIdForChannel(channel);\n if (!subscriberCountBySubscriptionId[subscriptionId] && amount > 0) {\n subscriberCountBySubscriptionId[subscriptionId] = 0;\n }\n const newCount = amount + subscriberCountBySubscriptionId[subscriptionId];\n if (newCount <= 0) {\n delete subscriberCountBySubscriptionId[subscriptionId];\n } else {\n subscriberCountBySubscriptionId[subscriptionId] = newCount;\n }\n return newCount;\n}\n\nconst cache = new WeakMap();\nfunction getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer<TNotification>(\n channel: RpcSubscriptionsChannel<unknown, RpcNotification<TNotification>>,\n subscribeRequest: RpcRequest,\n responseTransformer?: RpcResponseTransformer,\n): DataPublisher<{\n [channelName: `notification:${number}`]: TNotification;\n}> {\n let publisherByResponseTransformer = cache.get(channel);\n if (!publisherByResponseTransformer) {\n cache.set(channel, (publisherByResponseTransformer = new WeakMap()));\n }\n const responseTransformerKey = responseTransformer ?? channel;\n let publisher = publisherByResponseTransformer.get(responseTransformerKey);\n if (!publisher) {\n publisherByResponseTransformer.set(\n responseTransformerKey,\n (publisher = demultiplexDataPublisher(channel, 'message', rawMessage => {\n const message = rawMessage as RpcNotification<unknown> | RpcResponseData<unknown>;\n if (!('method' in message)) {\n return;\n }\n const transformedNotification = responseTransformer\n ? responseTransformer(message.params.result, subscribeRequest)\n : message.params.result;\n return [`notification:${message.params.subscription}`, transformedNotification];\n })),\n );\n }\n return publisher;\n}\n\n/**\n * Given a channel, this function executes the particular subscription plan required by the Solana\n * JSON RPC Subscriptions API.\n *\n * @param config\n *\n * 1. Calls the `subscribeRequest` on the remote RPC\n * 2. Waits for a response containing the subscription id\n * 3. Returns a {@link DataPublisher} that publishes notifications related to that subscriptions id,\n * filtering out all others\n * 4. Calls the `unsubscribeMethodName` on the remote RPC when the abort signal is fired.\n */\nexport async function executeRpcPubSubSubscriptionPlan<TNotification>({\n channel,\n responseTransformer,\n signal,\n subscribeRequest,\n unsubscribeMethodName,\n}: Config<TNotification>): Promise<DataPublisher<RpcSubscriptionNotificationEvents<TNotification>>> {\n let subscriptionId: number | undefined;\n channel.on(\n 'error',\n () => {\n // An error on the channel indicates that the subscriptions are dead.\n // There is no longer any sense hanging on to subscription ids.\n // Erasing it here will prevent the unsubscribe code from running.\n subscriptionId = undefined;\n subscriberCountBySubscriptionIdByChannel.delete(channel);\n },\n { signal },\n );\n /**\n * STEP 1\n * Create a promise that rejects if this subscription is aborted and sends\n * the unsubscribe message if the subscription is active at that time.\n */\n const abortPromise = new Promise<never>((_, reject) => {\n function handleAbort(this: AbortSignal) {\n /**\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they\n * will be assigned the same subscription id, and will occupy one subscription slot. We\n * must be careful not to send the unsubscribe message until the last subscriber aborts.\n */\n if (decrementSubscriberCountAndReturnNewCount(channel, subscriptionId) === 0) {\n const unsubscribePayload = createRpcMessage({\n methodName: unsubscribeMethodName,\n params: [subscriptionId],\n });\n subscriptionId = undefined;\n channel.send(unsubscribePayload).catch(() => {});\n }\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n }\n if (signal.aborted) {\n handleAbort.call(signal);\n } else {\n signal.addEventListener('abort', handleAbort);\n }\n });\n /**\n * STEP 2\n * Send the subscription request.\n */\n const subscribePayload = createRpcMessage(subscribeRequest);\n await channel.send(subscribePayload);\n /**\n * STEP 3\n * Wait for the acknowledgement from the server with the subscription id.\n */\n const subscriptionIdPromise = new Promise<RpcSubscriptionId>((resolve, reject) => {\n const abortController = new AbortController();\n signal.addEventListener('abort', abortController.abort.bind(abortController));\n const options = { signal: abortController.signal } as const;\n channel.on(\n 'error',\n err => {\n abortController.abort();\n reject(err);\n },\n options,\n );\n channel.on(\n 'message',\n message => {\n if (message && typeof message === 'object' && 'id' in message && message.id === subscribePayload.id) {\n abortController.abort();\n if ('error' in message) {\n reject(getSolanaErrorFromJsonRpcError(message.error));\n } else {\n resolve(message.result);\n }\n }\n },\n options,\n );\n });\n subscriptionId = await safeRace([abortPromise, subscriptionIdPromise]);\n if (subscriptionId == null) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__EXPECTED_SERVER_SUBSCRIPTION_ID);\n }\n incrementSubscriberCount(channel, subscriptionId);\n /**\n * STEP 4\n * Filter out notifications unrelated to this subscription.\n */\n const notificationPublisher = getMemoizedDemultiplexedNotificationPublisherFromChannelAndResponseTransformer(\n channel,\n subscribeRequest,\n responseTransformer,\n );\n const notificationKey = `notification:${subscriptionId}` as const;\n return {\n on(type, listener, options) {\n switch (type) {\n case 'notification':\n return notificationPublisher.on(\n notificationKey,\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['notification']) => void,\n options,\n );\n case 'error':\n return channel.on(\n 'error',\n listener as (data: RpcSubscriptionNotificationEvents<TNotification>['error']) => void,\n options,\n );\n default:\n throw new SolanaError(SOLANA_ERROR__INVARIANT_VIOLATION__DATA_PUBLISHER_CHANNEL_UNIMPLEMENTED, {\n channelName: type,\n supportedChannelNames: ['notification', 'error'],\n });\n }\n },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/rpc-subscriptions-spec",
|
|
3
|
-
"version": "5.1.0-canary-
|
|
3
|
+
"version": "5.1.0-canary-20251203213248",
|
|
4
4
|
"description": "A generic implementation of JSON RPC Subscriptions using proxies",
|
|
5
5
|
"homepage": "https://www.solanakit.com/api#solanarpc-subscriptions-spec",
|
|
6
6
|
"exports": {
|
|
@@ -55,10 +55,10 @@
|
|
|
55
55
|
"maintained node versions"
|
|
56
56
|
],
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@solana/errors": "5.1.0-canary-
|
|
59
|
-
"@solana/promises": "5.1.0-canary-
|
|
60
|
-
"@solana/rpc-spec-types": "5.1.0-canary-
|
|
61
|
-
"@solana/subscribable": "5.1.0-canary-
|
|
58
|
+
"@solana/errors": "5.1.0-canary-20251203213248",
|
|
59
|
+
"@solana/promises": "5.1.0-canary-20251203213248",
|
|
60
|
+
"@solana/rpc-spec-types": "5.1.0-canary-20251203213248",
|
|
61
|
+
"@solana/subscribable": "5.1.0-canary-20251203213248"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"typescript": ">=5.3.3"
|